Jump to content


JCA

VBScript and HTA to associate computer and add to specific collections

Recommended Posts

Hello everyone!

  1. Use IIS Pool for Authentication and not have Userid and Password in clear text. (Thank you Niall!)

  1. My goal is to allow a third party company to Migrate user state from XP to Windows 7 during our Windows 7 Migration project. Doing this tasks through SCCM console isn't worth it when the 3rd party staff will be changing during the project.
     
     
    I need to have the Source Computer and the Destination computer do the following when the "Create Computer Associatation" button is pushed.
    1. Add Source and Destination computer to the Computer Association in SCCM OSD
    2. Add Source Computer to the Collection I called Scanstate
    3. Add Destination Computer to the Collection I called Loadstate

The Computer Association Script that does work perfectly! ( I took this script from some ones blog and I added a little changes)

 

 

<html>
<head>
<title>USMT | Windows 7 Image</title>

<script language="VBScript">Window.ResizeTo 913,810</script>
<script language="VBScript">Window.MoveTo ((Screen.AvailWidth -913) / 2), 10</script>
<HTA:APPLICATION
ID="objOSDReg"
APPLICATIONNAME="OSD_Registration"
SINGLEINSTANCE="yes"
BORDER="thin"
ICON="Deploy.ico"
MAXIMIZEBUTTON="no"
MINIMIZEBUTTON="yes"
NAVIGABLE="yes"
>
</head>
<script LANGUAGE="VBScript">
'Set Variables: Site Server, Username and Password
Server = "sccm server name"
userName = "userid"
userPassword = "password"
Sub AssociateCompAandCompB
Dim computera, computerb, ResIDA, ResIDB
 strcomputera = document.getElementById("computera").value
 strcomputerb = document.getElementById("computerb").value
Set connection = Connect(Server, userName, userPassword)
ResIDA = GetResourceIDFromName (connection, strcomputera)
ResIDB = GetResourceIDFromNameB (Connection, strcomputerb)
AssociateComputer Connection, ResIDA, ResIDB', ResIDA, ResIDB
End Sub
' -------------------------------------------------------------------------------------------------------------------
' Associate Computers in SCCM Computer Association
' -------------------------------------------------------------------------------------------------------------------
Sub AssociateComputer(connection, referenceComputerResourceId, destinationComputerResourceId)
Dim stateMigrationClass
Dim inParams
Dim outParams
 'On Error Resume Next
' Get the state migration class.
Set stateMigrationClass = connection.Get("SMS_StateMigration")
' Set up the parameters.
Set inParams = _
 	stateMigrationClass.Methods_("AddAssociation").InParameters.SpawnInstance_
inParams.SourceClientResourceID = referenceComputerResourceId
inParams.RestoreClientResourceID = destinationComputerResourceId
  ' Call the method
Set outParams = connection.ExecMethod( "SMS_StateMigration","AddAssociation",inParams)
'connection.ExecMethod stateMigrationClass.AddAssociation,inParams

  ' MsgBox Err
if Err.number <> 0 Then
   	MsgBox "Failed to create a Computer Association, please try again or contact the GOC"
   	Exit Sub
   	Else
   	General_OnClick()
End If
  End Sub
' -------------------------------------------------------------------------------------------------------------------
' Utility function to search for the site code
' -------------------------------------------------------------------------------------------------------------------
Function Connect(server, userName, userPassword)
'On Error Resume Next
Dim net
Dim localConnection
Dim swbemLocator
Dim swbemServices
Dim providerLoc
Dim location
Set swbemLocator = CreateObject("WbemScripting.SWbemLocator")'
swbemLocator.Security_.AuthenticationLevel = 6 'Packet Privacy.
' If the server is local, don't supply credentials.
Set net = CreateObject("WScript.NetWork")
If UCase(net.ComputerName) = UCase(server) Then
   	localConnection = True
   	userName = ""
   	userPassword = ""
   	server = "."
End If
' Connect to the server.
Set swbemServices= swbemLocator.ConnectServer _
       	(server, "root\sms",userName,userPassword)
If Err.Number<>0 Then
 	'  Wscript.Echo "Couldn't connect: " + Err.Description
   	Connect = Null
   	Exit Function
End If
' Determine where the provider is and connect.
Set providerLoc = swbemServices.InstancesOf("SMS_ProviderLocation")
   	For Each location In providerLoc
       	If location.ProviderForLocalSite = True Then
           	Set swbemServices = swbemLocator.ConnectServer _
    			(location.Machine, "root\sms\site_" + _
               	location.SiteCode,userName,userPassword)
           	If Err.Number<>0 Then
   	'	Wscript.Echo "Couldn't connect:" + Err.Description
               	Connect = Null
               	Exit Function
   	Else
       	'Wscript.Echo "Yay, we connected!!"
           	End If
           	Set Connect = swbemServices
           	Exit Function
       	End If
   	Next
Set Connect = null ' Failed to connect.
End Function
' -------------------------------------------------------------------------------------------------------------------
' -------------------------------------------------------------------------------------------------------------------
Function GetResourceIDFromName(connection, strcomputera)
'On Error Resume Next
' Build Query string.
query = "SELECT ResourceId FROM SMS_R_System WHERE NetbiosName = """ & strcomputera & """"
' Execute the query
Set result = connection.ExecQuery(query)
If Err then
   	CheckError
   	'MsgBox "error on a"
   	Exit Function
End If
' Walk through the elements of the enumerator.
' Assume there will only be 1 computer with the requested name, if any.
resourceID = 0  ' Assume the worst
For each r in result
   	GetResourceIDFromName = r.ResourceID
'MsgBox r.resourceID
Next
End Function
' -------------------------------------------------------------------------------------------------------------------
' -------------------------------------------------------------------------------------------------------------------
Function GetResourceIDFromNameB(connection, strcomputerb)
On Error Resume Next
' Build Query string.
query = "SELECT ResourceId FROM SMS_R_System WHERE NetbiosName = """ & strComputerB & """"
' Execute the query
Set result = connection.ExecQuery(query)
If Err then
   	CheckError
   	Exit Function
End If
' Walk through the elements of the enumerator.
' Assume there will only be 1 computer with the requested name, if any.
resourceID = 0  ' Assume the worst
For each b in result
   	GetResourceIDFromNameB = b.ResourceID
   	'MsgBox b.resourceID
Next
End Function
' -------------------------------------------------------------------------------------------------------------------
' -------------------------------------------------------------------------------------------------------------------
Sub General_OnClick()
   	strHtm = "<table class=""tbl"">"
   	strHtm = strHtm & "<tr><td>_________________________</td><td>_________________</td></tr>"
   	strHtm = strHtm & "<tr><td>Source Computer        	</td><td>" & document.getElementById("computera").value & "</td></tr><tr></tr>"
   	strHtm = strHtm & "<tr><td>_________________________</td><td>_________________</td></tr>"
   	strHtm = strHtm & "<tr><td>Destination Computer    	</td><td>" & document.getElementById("computerb").value & "</td></tr>"
       	strHtm = strHtm & "</table>"
   	'Next
   	dataarea.innerhtml = strHtm
End Sub
</SCRIPT>
<!-- -------------------------------------------------------------------------------------------------------------------  -->
<!--  HTML Starts                                                                                             			-->
<!-- -------------------------------------------------------------------------------------------------------------------  -->
<body style="font-family: Arial; background-image: url('Win7_wallpaper-blue2.jpg'); background-repeat: no-repeat; background-color: black; color: white;">
<!--OSD Registration Header-->
<table style="text-align: left; width: 100px;" border="0" cellpadding="2" cellspacing="2">
 <tbody>
<tr>
<td><big><big><big><big><span>    OSD</span></big></big></big></big></td>
 	<td style="text-align: right;"><span> powered<br> by</span></td>
 	<td><span><img style="width: 301px; height: 64px;" alt="System Center" src="file:logo-system-center.gif"></span></td>
</tr>
 </tbody>
</table>
<!--Line Break-->
<hr style="color:#00B2EE">
<!--Deployment Scenario Selection-->
<table align="center" width="90%">
 <tr><td>
 <h3>    Computer Association</h3>
 <!-- HTA Text Input Box for Computer A (Source)--><!-- HTA Text Input Box for Computer B (Destination)-->
  <p> 	Source Computer = <input type="text" id="ComputerA" size="18">  Destination Computer = <input type="text" id="ComputerB" size="18"></p>
 <!-- A - AssociateCompAandCompB --> <!-- Resets Page -->
 	<p> 	<input id=runbutton type="button" value="Create Computer Association" name="run_button"  onClick="AssociateCompAandCompB">
    	<input type="button" value="Reset Page" onClick="window.location.reload()"></p><BR>
</td></tr>
</table>

<!-- Display Data on HTA screen -->
<table align="center" width="85%">
 <tr><td>
  <!--Line Break-->
 	<div style="margin: 200px 130px 0px 0px; background-color: transparent; padding: 10px;">
 	<div> <hr style="color:#00B2EE">
 	<div> <h4>Computer Association Output<h4>
 	<div id="dataarea"></div>
 	</div>
 </td></tr>
</table>
<br><br>
<!--Version #-->
<small style="color: rgb(100,100,100)">  #1v1.0</small>
<table align="center" valign="center" width="100%">
<tr><big><big><span id="msgTXT"> </span></big></big><br></tr>
<tr style="color:red;"><big><big><span id="msgERR"> </span></big></big><br></tr>
</table>
</body>
</html>

Share this post


Link to post
Share on other sites


for the cleartext part, look at this post

Share this post


Link to post
Share on other sites

Thank you!

 

I wish I could figure out that Add computer to a specific collection. That's kiling me litteraly!

Share this post


Link to post
Share on other sites

Hmm... I don't really get your code and what you're trying to do... You already got the resourceID of the two machines and that's what you need, so I've got no clue what you are trying to achieve in this for For Each Computerselect in Computerlisting.Options

When you already have the resourceID you can just say newDirectRule.ResourceID = referenceComputerResourceId

 

Also, why two times a function that does the same... GetResourceIDFromName and GetResourceIDFromNameB....

Share this post


Link to post
Share on other sites

Peter, I typicaly don't write VBscript and HTA. I didn't mean to leave the section of code "Add Computer to Scanstate and Loadstate Collections in SCCM" to the first post. I found the code on the internet and have tried to modify this to do what I need.

 

My goal is to allow a third party company to Migrate user state from XP to Windows 7 during our Windows 7 Migration project. Doing this tasks through SCCM console isn't worth it when the 3rd party staff will be changing during the project.

 

I need to have the Source Computer and the Destination computer do the following when the "Create Computer Associatation" button is pushed.

1. Add Source and Destination computer to the Computer Association in SCCM OSD
2. Add Source Computer to the Collection I called Scanstate
3. Add Destination Computer to the Collection I called Loadstate

 

I'll keep you posted.

Share this post


Link to post
Share on other sites

I fixed it and it's finish! Here's the code if anyone wants it.

 

<html> 
<head> 
<title>USMT | Windows 7 Image</title>

<script language="VBScript">Window.ResizeTo 913,810</script>
<script language="VBScript">Window.MoveTo ((Screen.AvailWidth -913) / 2), 10</script>
<HTA:APPLICATION
ID="objOSDReg"
APPLICATIONNAME="OSD_Registration"
SINGLEINSTANCE="yes"
BORDER="thin"
ICON="Deploy.ico"
MAXIMIZEBUTTON="no"
MINIMIZEBUTTON="yes"
NAVIGABLE="yes"
> 
</head>
<script LANGUAGE="VBScript">
'Set Variables: Site Server, Username and Password 
'Server = "XXXXXXXXX"
'userName = "XXXXXXXXX"
'userPassword = "XXXXXXXXX"
 Dim computera, computerb, ResIDA, ResIDB, sccmserver, server, userid, userName, pswd, userpassword
 Dim strSourceResourceID, strDestinationResourceID, strCaptureCollectionID, strRestoreCollectionID, objSMS
 Sub AssociateCompAandCompB
'Server = document.getElementById("sccmserver").value
'username = document.getElementById("userid").value
'userpassword = document.getElementById("pswd").value
strcomputera = document.getElementById("computera").value 
strcomputerb = document.getElementById("computerb").value
strCaptureCollectionID = "OKE0033E"
strRestoreCollectionID = "OKE0033D"  
' connection to SCCM server
Set objSMS = Connect(Server, userName, userpassword) 
ResIDA = GetResourceIDFromName (objSMS, strcomputera) 
ResIDB = GetResourceIDFromNameB (objSMS, strcomputerb)
	'AddtoCollection
 If (ResIDA <> 0) And (ResIDB <> 0) Then
  AssociateComputer objSMS, ResIDA, ResIDB
  AddtoCollection strcomputerA, ResIDA, strCaptureCollectionID
  AddtoCollection strcomputerb, ResIDB, strRestoreCollectionID
  Else
  General_OnClick()
 End If
End Sub 
' -------------------------------------------------------------------------------------------------------------------
' Associate Computers in SCCM Computer Association
' -------------------------------------------------------------------------------------------------------------------
Sub AssociateComputer(objSMS, referenceComputerResourceId, destinationComputerResourceId) 
Dim stateMigrationClass 
Dim inParams 
Dim outParams 
 'On Error Resume Next 
' Get the state migration class. 
Set stateMigrationClass = objSMS.Get("SMS_StateMigration")
' Set up the parameters. 
Set inParams = _ 
 	stateMigrationClass.Methods_("AddAssociation").InParameters.SpawnInstance_ 
inParams.SourceClientResourceID = referenceComputerResourceId 
inParams.RestoreClientResourceID = destinationComputerResourceId
' Call the method 
Set outParams = objSMS.ExecMethod( "SMS_StateMigration","AddAssociation",inParams) 

  ' MsgBox Err 
if Err.number <> 0 Then 
   	MsgBox "Failed to create a Computer Association, please try again or contact the Windows Deployment Team Lead" 
   	Exit Sub 
   	Else 
   	General_OnClick() 
End If 
  End Sub 
' -------------------------------------------------------------------------------------------------------------------
'AddtoCollection(name, ResourceID, collectionID)
' -------------------------------------------------------------------------------------------------------------------
Sub AddtoCollection(name, ResourceID, collectionID)
'Sub AddtoCollection(connection, referenceComputerResourceId, destinationComputerResourceId)
 	'Dim instColl
 	'Dim instDirectRule
'if one exists create a collection rule
Set instColl = objSMS.Get("SMS_Collection.CollectionID="&"""" & collectionID & """")
Set instDirectRule = objSMS.Get("SMS_CollectionRuleDirect").SpawnInstance_ ()
instDirectRule.ResourceClassName = "SMS_R_System"
instDirectRule.ResourceID = ResourceID
instDirectRule.RuleName = name & " - " & ResourceID
instColl.AddMembershipRule instDirectRule , SMSContext
instColl.RequestRefresh False
' log name & " Added to " & Instcoll.Name
' wscript.echo(name & " Added to " & Instcoll.Name)
MsgBox (name & " Added to " & Instcoll.Name)
  ' MsgBox Err 
if Err.number <> 0 Then 
   	MsgBox "Failed to create a Computer Association, please try again or contact the Windows Deployment Team Lead" 
   	Exit Sub 
   	Else 
   	General_OnClick() 
End If 
End Sub
' -------------------------------------------------------------------------------------------------------------------
' Utility function to search for the site code 
' -------------------------------------------------------------------------------------------------------------------
Function Connect(server, userName, userPassword)
'On Error Resume Next
	Dim net 
Dim localConnection 
Dim swbemLocator 
Dim swbemServices 
Dim providerLoc 
Dim location 
Set swbemLocator = CreateObject("WbemScripting.SWbemLocator")'
	swbemLocator.Security_.AuthenticationLevel = 6 'Packet Privacy. 
' If the server is local, don't supply credentials. 
'	Set net = CreateObject("WScript.NetWork") 
'	If UCase(net.ComputerName) = UCase(server) Then 
'    	localConnection = True 
'    	userName = "" 
'    	userPassword = "" 
'    	server = "." 
'	End If 
' Connect to the server. 
Set swbemServices= swbemLocator.ConnectServer _ 
       	(server, "root\sms",userName,userPassword) 
If Err.Number<>0 Then 
 	'  Wscript.Echo "Couldn't connect: " + Err.Description 
   	Connect = Null 
   	Exit Function 
End If
	' Determine where the provider is and connect. 
Set providerLoc = swbemServices.InstancesOf("SMS_ProviderLocation") 
   	For Each location In providerLoc 
       	If location.ProviderForLocalSite = True Then 
           	Set swbemServices = swbemLocator.ConnectServer _ 
            	(location.Machine, "root\sms\site_" + _ 
               	location.SiteCode,userName,userPassword) 
           	If Err.Number<>0 Then 
   	'	Wscript.Echo "Couldn't connect:" + Err.Description 
               	Connect = Null 
               	Exit Function 
   	Else 
       	'Wscript.Echo "Yay, we connected!!" 
           	End If 
           	Set Connect = swbemServices 
           	Exit Function 
       	End If 
   	Next 
Set Connect = null ' Failed to connect. 
End Function 
' -------------------------------------------------------------------------------------------------------------------
' GetResourceID From Name A
' -------------------------------------------------------------------------------------------------------------------
Function GetResourceIDFromName(objSMS, strcomputera)
	'On Error Resume Next 
' Build Query string. 
query = "SELECT ResourceId FROM SMS_R_System WHERE NetbiosName = """ & strcomputera & """" 
' Execute the query 
'Set result = connection.ExecQuery(query) 
Set result = objSMS.ExecQuery(query) 
If Err then 
   	CheckError 
   	'MsgBox "error on a" 
   	Exit Function 
End If 
' Walk through the elements of the enumerator. 
' Assume there will only be 1 computer with the requested name, if any. 
resourceID = 0  ' Assume the worst 
For each r in result 
   	GetResourceIDFromName = r.ResourceID 
'MsgBox r.resourceID 
Next
End Function 
' -------------------------------------------------------------------------------------------------------------------
' GetResourceID From Name B
' -------------------------------------------------------------------------------------------------------------------
Function GetResourceIDFromNameB(objSMS, strcomputerb)
	On Error Resume Next 
' Build Query string. 
query = "SELECT ResourceId FROM SMS_R_System WHERE NetbiosName = """ & strComputerB & """" 
' Execute the query 
Set result = objSMS.ExecQuery(query) 
'Set result = connection.ExecQuery(query) 
If Err then 
   	CheckError 
   	Exit Function 
End If 
' Walk through the elements of the enumerator. 
' Assume there will only be 1 computer with the requested name, if any. 
resourceID = 0  ' Assume the worst 
For each b in result 
   	GetResourceIDFromNameB = b.ResourceID 
   	'MsgBox b.resourceID 
Next
End Function
' -------------------------------------------------------------------------------------------------------------------
' -------------------------------------------------------------------------------------------------------------------
Sub General_OnClick()
   	strHtm = "<table class=""tbl"">"
   	strHtm = strHtm & "<tr><td>_________________________</td><td>_________________</td></tr>" 
   	strHtm = strHtm & "<tr><td>Source Computer        	</td><td>" & document.getElementById("computera").value & "</td></tr><tr></tr>" 
   	strHtm = strHtm & "<tr><td>_________________________</td><td>_________________</td></tr>" 
   	strHtm = strHtm & "<tr><td>Destination Computer    	</td><td>" & document.getElementById("computerb").value & "</td></tr>" 
       	strHtm = strHtm & "</table>" 
   	'Next 
   	dataarea.innerhtml = strHtm 
End Sub
</SCRIPT>
<!-- -------------------------------------------------------------------------------------------------------------------  -->
<!--  HTML Starts                                                                                                     	-->
<!-- -------------------------------------------------------------------------------------------------------------------  -->
<body style="font-family: Arial; background-image: url('Win7_wallpaper-blue2.jpg'); background-repeat: no-repeat; background-color: black; color: white;">
<!--OSD Registration Header-->
<table style="text-align: left; width: 100px;" border="0" cellpadding="2" cellspacing="2">
 <tbody>
<tr>
<td><big><big><big><big><span>    OSD</span></big></big></big></big></td>
 	<td style="text-align: right;"><span> powered<br> by</span></td>
 	<td><span><img style="width: 301px; height: 64px;" alt="System Center" src="file:logo-system-center.gif"></span></td>
</tr>
 </tbody>
</table>
<!--Line Break-->
<hr style="color:#00B2EE">
<!--Deployment Scenario Selection-->
 <table align="center" width="90%">
 <tr><td>
 <h3>    Server Connection</h3>
 <!-- HTA Text Input Box for Server-->
  <p>     Server:          <input type="text" id="sccmserver" size="18"><BR>
       UserName:   <input type="text" id="userid" size="18"><BR>
       Password:    <input type="password" id="pswd" size="18"></p>
 </td></tr>
</table>

<table align="center" width="90%">
 <tr><td> <BR>
 <h3>    Computer Association</h3>
 <!-- HTA Text Input Box for Computer A (Source)--><!-- HTA Text Input Box for Computer B (Destination)-->
  <p>     Source Computer:          <input type="text" id="ComputerA" size="15"><BR>
       Destination Computer:   <input type="text" id="ComputerB" size="15"></p>
 <!-- A - AssociateCompAandCompB --> <!-- Resets Page -->
 	<p>     <input id=runbutton type="button" value="Create Computer Association" name="run_button"  onClick="AssociateCompAandCompB">
 	   <input type="button" value="Reset Page" onClick="window.location.reload()"></p><BR>
	</td></tr>
</table>

<!-- Display Data on HTA screen -->
<table align="center" width="85%">
 <tr><td>
  <!--Line Break-->
 	<div style="margin: 25px 100px 0px 0px; background-color: transparent; padding: 10px;">
 	<div> <hr style="color:#00B2EE">
 	<div> <h4>Computer Association Output<h4>
 	<div id="dataarea"></div> 
 	</div> 
 </td></tr>
</table>
<br><br>
<!--Version #-->
<small style="color: rgb(100,100,100)">  #1v1.1</small>
<table align="center" valign="center" width="100%">
<tr><big><big><span id="msgTXT"> </span></big></big><br></tr>
<tr style="color:red;"><big><big><span id="msgERR"> </span></big></big><br></tr>
</table>
</body>
</html>

  • Like 1

Share this post


Link to post
Share on other sites

JCA, this looks awesome!

 

If I need to tweak this for my environment, where do I put the names in for my USMT Capture and Restore Collections?

 

Also, I'm not sure I understand where to use this tool.

 

Do I make this part of a Task Sequence as listed here (http://www.windows-n...display-my-hta/) then advertise it as a voluntary PXE advertisement to all of my systems? Then my tech guys just hit F12 for PXE boot and fill in the values on this HTA?

 

Thanks for posting this fantastic tool here, your peers thank you!

 

EDIT : I looked deeper into the matter, you would add this to your Task Sequence as one of the first steps.

Share this post


Link to post
Share on other sites

I took this script and customized it to my environment. I changed it so that it will use the computer name of the computer it is running from as computer a, so the user only has to enter the destination computer. I also added an exit button.

 

I do have one problem though. The computer association gets created in SCCM, and the data is backed up to the SMP just fine. But, in the migrationstatus.xml that gets created, it has the same GUID for the source and destination computer, even though the SCCM console shows a computer association created with the correct source and destination computer names..

 

This causes the 'Request State Store' step on the data restore task sequence to fail. If I manually change the guid in the xml file to the correct guid of the destination computer, it completes perfectly..

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...