Tag Archives | PowerShell

PowerShell script to set the State of a record in Microsoft CRM 2011 (SOAP)

I wanted to mark a meeting/appointment as completed via code. I came up with the PowerShell script below. Maybe it will be of use to some one?


FUNCTION JBM-CRM-SetState {
PARAM(
    [string][ValidateSet("crmserver.company.com", "dev-crmserver.company.com")]$ServerName="crm.sardverb.com",
    [string][ValidateSet("CRMOrganizationName")]$OrganizationName="SardVerbinnen",
    [string][parameter(Mandatory=$true)][ValidateSet("email", "phonecall", "appointment")]$EntityType,
    [string][parameter(Mandatory=$true)][ValidateScript({ $_ -match("^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$")})]$TargetGUID,
    $State=1,$Status=3,[switch]$MyDebug
    )
$requestMain = ""
$requestMain += "<s:Envelope xmlns:s=`"http://schemas.xmlsoap.org/soap/envelope/`">";
$requestMain += "  <s:Body>";
$requestMain += "    <Execute xmlns=`"http://schemas.microsoft.com/xrm/2011/Contracts/Services`" xmlns:i=`"http://www.w3.org/2001/XMLSchema-instance`">";
$requestMain += "      <request i:type=`"b:SetStateRequest`" xmlns:a=`"http://schemas.microsoft.com/xrm/2011/Contracts`" xmlns:b=`"http://schemas.microsoft.com/crm/2011/Contracts`">";
$requestMain += "        <a:Parameters xmlns:c=`"http://schemas.datacontract.org/2004/07/System.Collections.Generic`">";
$requestMain += "          <a:KeyValuePairOfstringanyType>";
$requestMain += "            <c:key>EntityMoniker</c:key>";
$requestMain += "            <c:value i:type=`"a:EntityReference`">";
$requestMain += "              <a:Id>$TargetGUID</a:Id>";
$requestMain += "              <a:LogicalName>$EntityType</a:LogicalName>";
$requestMain += "              <a:Name i:nil=`"true`" />";
$requestMain += "            </c:value>";
$requestMain += "          </a:KeyValuePairOfstringanyType>";
$requestMain += "          <a:KeyValuePairOfstringanyType>";
$requestMain += "            <c:key>State</c:key>";
$requestMain += "            <c:value i:type=`"a:OptionSetValue`">";
$requestMain += "              <a:Value>$State</a:Value>";
$requestMain += "            </c:value>";
$requestMain += "          </a:KeyValuePairOfstringanyType>";
$requestMain += "          <a:KeyValuePairOfstringanyType>";
$requestMain += "            <c:key>Status</c:key>";
$requestMain += "            <c:value i:type=`"a:OptionSetValue`">";
$requestMain += "              <a:Value>$Status</a:Value>";
$requestMain += "            </c:value>";
$requestMain += "          </a:KeyValuePairOfstringanyType>";
$requestMain += "        </a:Parameters>";
$requestMain += "        <a:RequestId i:nil=`"true`" />";
$requestMain += "        <a:RequestName>SetState</a:RequestName>";
$requestMain += "      </request>";
$requestMain += "    </Execute>";
$requestMain += "  </s:Body>";
$requestMain += "</s:Envelope>";
if ($MyDebug){write-host $requestMain}

$url="http://$ServerName/$OrganizationName/XRMServices/2011/Organization.svc/web"

$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.Open('POST', $url, $false)
$http_request.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
$http_request.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
$http_request.setRequestHeader("Content-Length", $xml.length);
$http_request.send($requestMain);
if ($MyDebug){$http_request.responseText}
}

Use PowerShell to get Google Analytics data

I wanted to write a powershell script that will retrieve the number of visits for my site. I put the following script together. Note this uses Google’s ClientLogin for authentication, which is deprecated. I have not worked with OAuth 2 yet.


function JBM-GA-GetStats {
PARAM([string][ValidateSet("CurrentMonth","LastMonth","Today","Yesterday")]$Range="CurrentMonth",
        $GAId="XXXXXXXX",$email="email@company.com",[switch]$MyDebug)

[datetime]$Today=[datetime]::Today
[datetime]$Yesterday=[datetime]::Today.AddDays(-1)
[datetime]$FirstDayCurrentMonth=$Today.AddDays(- ($Today.Day - 1))
[datetime]$FirstDayPreviousMonth=$FirstDayCurrentMonth.AddMonths(-1)
[datetime]$LastDayPreviousMonth=$FirstDayCurrentMonth.AddDays(-1)

switch ($Range){
    "CurrentMonth" {
        $startdate=$FirstDayCurrentMonth.ToString("yyyy-MM-dd")
        $enddate=$Today.ToString("yyyy-MM-dd")
    }
    "LastMonth" {
        $startdate=$FirstDayPreviousMonth.ToString("yyyy-MM-dd")
        $enddate=$LastDayPreviousMonth.ToString("yyyy-MM-dd")        
    }
    "Today" {
        $startdate=$Today.ToString("yyyy-MM-dd")
        $enddate=$Today.ToString("yyyy-MM-dd")   
    }
    "Yesterday"{
        $startdate=$Yesterday.ToString("yyyy-MM-dd")
        $enddate=$Yesterday.ToString("yyyy-MM-dd")   
    }
}

$pw = read-host "Please Enter Your Password" -AsSecureString

$null = [Reflection.Assembly]::LoadWithPartialName("System.Web")   
$password= "Passwd=$([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($pw)))"

#getting my auth token
$url="https://www.google.com/accounts/ClientLogin?Email=$($email)&$($password)&accountType=GOOGLE&source=mysource&service=analytics"
if ($MyDebug){write-host $url}
$webclient = new-object System.Net.WebClient
$dataString=$webclient.DownloadString($url)
$Auth=$dataString.split("`n")[2].split("=")[1]
if ($MyDebug){write-host $Auth}

#Connecting using auth token to get my data
$webclient.Headers.Add("Authorization", "GoogleLogin auth=$($Auth)")
$url="https://www.google.com/analytics/feeds/data?ids=ga%3A$($GAId)&metrics=ga%3Avisits&start-date=$($startdate)&end-date=$($enddate)&max-results=50"
if ($MyDebug){write-host $url}
$results=$webclient.DownloadString($url)

write-host ("$($Range)'s $($results.feed.entry.metric.name): $($results.feed.entry.metric.value)")
}


PowerShell script to create a SystemUser in Microsoft CRM 2011

I wanted to bulk create a bunch of users in CRM. PowerShell and the Microsoft CRM 2011 REST/OData endpoint make it easy. Here is a function to create a SystemUser via PowerShell

FUNCTION JBMURPHY-CRM-CreateSystemUser {
PARAM([string][ValidateSet("crmserver.company.com", "dev-crmserver.company.com")]$ServerName="crmserver.company.com",
[string][ValidateSet("CRMOrganizationName")]$OrganizationName="CRMOrganizationName",
[string]$BusinessUnitId="BusinessUnitGUID",
[string]$SystemUserDomain="CRMSystemUserDomain",
[string][parameter(Mandatory=$true)]$FirstName,
[string][parameter(Mandatory=$true)]$LastName,
[string][parameter(Mandatory=$true)]$UserName,[switch]$MyDebug
)
[string]$url="http://$ServerName/$($OrganizationName)/xrmservices/2011/OrganizationData.svc/SystemUserSet"

$SystemUserInfo = @{
DomainName="$($UserName)@$($SystemUserDomain)"
FirstName=$FirstName
LastName=$LastName
BusinessUnitId=@{LogicalName="businessunit";Id=$BusinessUnitId}
}
$assembly = [Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$json=new-object System.Web.Script.Serialization.JavaScriptSerializer
$SystemUserInfoData=$json.Serialize($SystemUserInfo)

$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.open('POST', $url, $false)
$http_request.setRequestHeader("Accept", "application/json")
$http_request.setRequestHeader("Content-Type", "application/json; charset=utf-8")
$results=$http_request.send($SystemUserInfoData)
if ($MyDebug){
$http_request.statusText
$http_request
}
$SystemUserId=$($json.DeserializeObject($http_request.responseText)).d.SystemUserId
return $SystemUserId
}

PowerShell script to create a contact in Microsoft CRM 2011 via REST/ODATA

Below is a PowerShell function to create a contact in CRM 2011. Hope it is helpful to some one.

FUNCTION JBM-CRM-CreateContact {
PARAM(
    [string][ValidateSet("crmserver.company.com", "dev-crmserver.company.com")]$ServerName="crmserver.company.com",
    [string][string][ValidateSet("CRMOrganizationName")]$OrganizationName="CRMOrganizationName",
    [string][parameter(Mandatory=$true)]$FirstName,
    [string][parameter(Mandatory=$true)]$LastName,
    [string]$MiddleName,[string]$Suffix,[string]$Email,[string]$JobTitle,
    [string]$Telephone,[string]$Description,[string]$ParentCustomerId,[string]$Address_Line1,[string]$Address_Line2,
    [string]$Address1_Country,[string]$Address1_PostalCode,[switch]$MyDebug
    )

$ContactInfo = @{
FirstName=$FirstName
LastName=$LastName
MiddleName=$MiddleName
Suffix=$Suffix
EMailAddress1=$Email
NickName=$NickName
JobTitle=$JobTitle
Telephone1=$Telephone
Address1_Line1=$Address_Line1
Address1_Line2=$Address_Line2
Address1_City=$Address1_City
Address1_PostalCode=$Address1_PostalCode
Address1_Country=$Address1_Country
Description=$Description
}
if (!($ParentCustomerId -eq "")){
$ContactInfo.Add("ParentCustomerId" , @{Id=$ParentCustomerId;LogicalName= "account"})
}

if ($MyDebug){
$ParentCustomerId
$ContactInfo
}

$assembly = [Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$json=new-object System.Web.Script.Serialization.JavaScriptSerializer
$ContactInfoData=$json.Serialize($ContactInfo)

$url="http://$ServerName/$($OrganizationName)/xrmservices/2011/OrganizationData.svc/ContactSet"
 
$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.open('POST', $url, $false)
$http_request.setRequestHeader("Accept", "application/json")
$http_request.setRequestHeader("Content-Type", "application/json; charset=utf-8")
$results=$http_request.send($ContactInfoData)
if ($MyDebug){
$http_request.statusText
$http_request
}
$ContactId=$($json.DeserializeObject($http_request.responseText)).d.ContactId
return $ContactId
}

PowerShell script to add an activity via OData/REST

I wanted to create some crm activities based on data in a spreadsheet. Looping thorough the csv file would be easy, the challenge came when I wanted to create new activities in Microsoft CRM 2011, specifically appointments. Below is a PowerShell function that I pieced together to create a new activity if you know GUIDs of the contacts for the regarding, required fields. This is a more fleshed out function compared to this

FUNCTION JBM-CRM-CreateActivityODATA {
PARAM([string][parameter(Mandatory=$true)][ValidateSet("Email", "PhoneCall", "Appointment")]$EntityType,
    [string][ValidateSet("crmserver.company.com", "dev-crmserver.company.com")]$ServerName="crmserver.company.com",
    [string][ValidateSet("CRMOrganizationName")]$OrganizationName="CRMOrganizationName",
    [string][parameter(Mandatory=$true)][ValidateScript({ $_ -match("^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$")})]$OwnerGUID,
    [string][ValidateScript({ $_ -match("^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$")})]$RegardingGUID,
    [ValidateScript({-not @( $_ | where {$_ -notmatch("^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$") }).Count})]$ReqiredGUIDs,
    [string]$Subject,[string]$Description,[datetime]$ScheduledStart,[datetime]$ScheduledEnd,[string]$Location
    )

Function CreateActivityParty{
    PARAM($ActivityId,$ParticipationTypeMask,$EntityType,$GUIDs)

    foreach ($Id in $GUIDs){
    $activityParty = @{}
    write-host $Id
    $activityParty.Add("PartyId", @{Id= $Id;LogicalName= "contact"})
    $activityParty.Add("ActivityId", @{Id= $ActivityId;LogicalName= "$($EntityType.ToLower())"})
    $activityParty.Add("ParticipationTypeMask" , @{ Value=$ParticipationTypeMask })
    $json=new-object System.Web.Script.Serialization.JavaScriptSerializer
    $activityPartyData=$json.Serialize($activityParty)
    $activityPartyData

    $url="http://$ServerName/$($OrganizationName)/xrmservices/2011/OrganizationData.svc/ActivityPartySet"
 
    $http_request = New-Object -ComObject Msxml2.XMLHTTP
    $http_request.open('POST', $url, $false)
    $http_request.setRequestHeader("Accept", "application/json")
    $http_request.setRequestHeader("Content-Type", "application/json; charset=utf-8")
    $http_request.send($activityPartyData)
    $http_request.statusText
    $results=$http_request
    }
}

$assembly = [Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$activityObject = @{
ActivityTypeCode=$EntityType
Subject=$Subject
Description=$Description
ScheduledStart=$($ScheduledStart.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"))
ScheduledEnd=$($ScheduledEnd.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"))
Location=$Location
RegardingObjectId=@{
Id= $RegardingGUID
LogicalName= "contact"
}
}

$json = new-object System.Web.Script.Serialization.JavaScriptSerializer
$activityData=$json.Serialize($activityObject)


$url="http://$ServerName/$($OrganizationName)/xrmservices/2011/OrganizationData.svc/$($EntityType)Set"
 
$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.open('POST', $url, $false)
$http_request.setRequestHeader("Accept", "application/json")
$http_request.setRequestHeader("Content-Type", "application/json; charset=utf-8")
$http_request.send($activityData)
$results=$http_request
$ActivityId=$($json.DeserializeObject($results.responseText)).d.ActivityId

# Set Required Attendees
CreateActivityParty -ActivityId $ActivityId -ParticipationTypeMask 5 -EntityType $EntityType -GUID $ReqiredGUIDs
# Set Orgaizer
CreateActivityParty -ActivityId $ActivityId -ParticipationTypeMask 7 -EntityType $EntityType -GUID $OwnerGUID
}

5 PowerShell functions to create a SCCM “trickle install” – i.e. X at a time.

If you look at this post, I describe a my idea of a SCCM trickle install – that is X number of machines at a time. Rather that have the install hit the whole collection at once, I wanted to hit just 20 a night. That way if there is an error, we can put the breaks on the deployment. We create dynamic collections that use a “NOT IN” SQL statement – this results in all the machines that are in the collection need the specific software. This script copies X at a time from that collection to new collection.

In the previous post, I run a VBScript that loops through the first 10 (or X) number of machines in the collection and add them to a new collection that contains the assigned advertisement. The next night, the script runs again, and the next 10 (or X) are copied (since the source collection is dynamic, the machines from the night before are removed).

I wanted to do the same thing, but I wanted to use PowerShell. First up, a function to find a Collection’s Id.

FUNCTION JBM-SCCM-GetCollection {
	Param([parameter(Mandatory = $true)]$CollectionName,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
	$QUERY="Select CollectionID from SMS_Collection WHERE Name = '$CollectionName'"
	Return $(Get-WmiObject -namespace $SCCMNameSpace -computer $SCCMServer -query $QUERY)
}

Next a function to find all the machines in a collection:

FUNCTION JBM-SCCM-GetCollectionMembers{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
	$QUERY="SELECT Name FROM SMS_FullCollectionMembership WHERE CollectionID = '$CollectionID'"
	Return $(Get-WmiObject -namespace $SCCMNameSpace -computer $SCCMServer -query $QUERY)
}

Next a function to remove all machines in a collection (the ones that are directly added)

FUNCTION JBM-SCCM-DeleteAllCollectionMembers{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com")
	$SCCMNameSpace="root\sms\site_$SiteName"
    $Collection=[WMI]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID='$CollectionID'"
	ForEach ($Rule in  $Collection.CollectionRules ){
    $Collection.DeleteMembershipRule($Rule)
    }
}

Next, a function to add a machine to a Collection:

FUNCTION JBM-SCCM-AddCollectionMember{
Param([parameter(Mandatory = $true)]$CollectionID,
	$SiteName="JBM",
	$SCCMServer="sccmserver.domain.com",
    [parameter(Mandatory = $true)]$ComputerToAdd)
	$SCCMNameSpace="root\sms\site_$SiteName"

    $computer = gwmi -computer $SCCMServer -namespace $SCCMNameSpace -Query "select * from SMS_R_System where NetBiosName='$ComputerToAdd'"
    $Collection=[WMI]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_Collection.CollectionID='$CollectionID'"
    $ruleClass = [wmiclass]"\\$($SCCMServer)\$($SCCMNameSpace):SMS_CollectionRuleDirect"
    $newRule = $ruleClass.CreateInstance() 
    $newRule.RuleName = $ComputerToAdd 
    $newRule.ResourceClassName = "SMS_R_System" 
    $newRule.ResourceID = $computer.ResourceID 
    $null = $Collection.AddMembershipRule($newRule) 
}

Finally, a function to copy machines from one collection to another, using the functions above:

FUNCTION JBM-SCCM-CopyCollectionMembers {
Param([parameter(Mandatory = $true)]$SourceCollectionName,
    [parameter(Mandatory = $true)]$DestinationCollectionName,
    [parameter(Mandatory = $true)]$NumberToCopy)

    $SrcCollID=JBM-SCCM-GetCollection($SourceCollectionName)
    $DstCollID=JBM-SCCM-GetCollection($DestinationCollectionName)
    $SrcCollMembers=JBM-SCCM-GetCollectionMembers($SrcCollID.CollectionID)
    JBM-SCCM-DeleteAllCollectionMembers($DstCollID.CollectionID)
    foreach ($Computer in $($SrcCollMembers | select -first $NumberToCopy)){
    JBM-SCCM-AddCollectionMember -CollectionID $DstCollID.CollectionID -ComputerToAdd $Computer.Name
    }

}

The result – a trickle install.

PowerShell script to create a SCCM Package,Program and Queries

I wanted to automate the process of creating a new package. The following code will look at an XML file for values (same xml file I am using here) and create a package based on the values. A lot of SCCM PowerShell was gathered from here. Here is the example of the source XML file:

<Install>
<Params>
<PkgName Value="Firefox" />
<PkgManufacturer Value="Mozilla" />
<PkgVersion Value="12.0" />
<PkgSourcePath Value="\\domain.local\DFSRoot\Path\Mozilla\Firefox-12.0" />
<PkgcontainerNodeID Value="17" />
<CurrentVersionQueryName Value="Software-MozillaFirefox-12.0" />
<OtherThanQueryName Value="Software-MozillaFirefox-OtherThan-12.0" />
<QuerycontainerNodeID Value="4" />
</Params>
</Install>

And here is the script that creates the package, program, distribution point,and 2 queries (A query to show where version is installed, and a second to show where it is not installed (NOT IN).)

function JBMMURPHY-SCCM-CreatePackageAndQueries{
PARAM(
    [Parameter(Mandatory=$true)]
    [ValidateScript({Test-Path $_})]
    $XMLFilePath)
[ xml ]$s = Get-Content $XMLFilePath

$NAMESPACE="root\SMS\Site_LAB"
$PkgName=$s.Install.SCCMParams.PkgName.Value
$PkgManufacturer=$s.Install.SCCMParams.PkgManufacturer.Value
$PkgVersion=$s.Install.SCCMParams.PkgVersion.Value
$PkgSourcePath=$s.Install.SCCMParams.PkgSourcePath.Value
$PkgcontainerNodeID=$s.Install.SCCMParams.PkgcontainerNodeID.Value
$OtherThanQueryName=$s.Install.SCCMParams.OtherThanQueryName.Value
$CurrentVersionQueryName=$s.Install.SCCMParams.CurrentVersionQueryName.Value
$QuerycontainerNodeID=$s.Install.SCCMParams.QuerycontainerNodeID.Value
$PkgProgramFlags=135308289
$PkgCommandLine = "powershell .\SVCInstall.ps1"

## create package and move into appropriate folder
$PackageProperties = @{
Name = $PkgName;
Manufacturer = $PkgManufacturer;
Version = $PkgVersion;
Language = "English (United States)";
PackageType = 0;
PkgSourceFlag = 2;
PkgSourcePath = $PkgSourcePath
Priority = 2
}
$newPackage = Set-WmiInstance -class SMS_Package -arguments $PackageProperties -namespace $NAMESPACE
$newPackage | Format-List | Out-Null
write-host "pkgid=$($newPackage.PackageID)"

## Move Package
$MovePackage = @{
InstanceKey = $newPackage.PackageID;
ObjectType = 2;
ContainerNodeID = $PkgcontainerNodeID
}
Set-WmiInstance -Class SMS_ObjectContainerItem -arguments $MovePackage -namespace $NAMESPACE

## create new program = Per-system unattended

$NewProgram = @{
PackageID = $newPackage.PackageID;
ProgramFlags = $PkgProgramFlags;
ProgramName = "Per-system unattended";
CommandLine = $PkgCommandLine
}
Set-WmiInstance -class SMS_Program -arguments $NewProgram -namespace $NAMESPACE

## Add Distribution point to package

$NewDistPointForPackage = @{
PackageID = $newPackage.PackageID;
ServerNALPath = '["Display=\\SERVENAME\"]MSWNET:["SMS_SITE=LAB"]\\SERVERNAME\';
SiteCode = "LAB";
SiteName = "LAB";
SourceSite = "LAB";
ResourceType = "Windows NT Server"
}
Set-WmiInstance -class SMS_DistributionPoint -arguments $NewDistPointForPackage -namespace $NAMESPACE


## Creating Queries

## Current Verson Query
$CurrentVersionQuery="select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like `'$($PkgName)%`' and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = `'$($PkgVersion)`' order by SMS_R_System.Name";
$CurrentVersionQueryHash = @{
Name = $CurrentVersionQueryName;
Expression = $CurrentVersionQuery;
TargetClassName = "SMS_R_System"
}
$newCurrentVersionQuery = Set-WmiInstance -class SMS_Query -arguments $CurrentVersionQueryHash -namespace $NAMESPACE
$newCurrentVersionQuery  | Format-List | Out-Null

$MoveCurrentVersionQuery=@{
InstanceKey = $newCurrentVersionQuery.QueryID;
ObjectType = 7;
ContainerNodeID = $QuerycontainerNodeID
}
Set-WmiInstance -Class SMS_ObjectContainerItem -arguments $MoveCurrentVersionQuery -namespace $NAMESPACE


## Other Than Query
$OtherThanQuery="select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like `'$($PkgName)%`' and SMS_R_System.Name not in (select SMS_R_System.Name from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like `'$($PkgName)%`' and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = `'$($PkgVersion)`') order by SMS_R_System.Name"
$OtherThanQueryHash =@{
Name = $OtherThanQueryName;
Expression = $OtherThanQuery;
TargetClassName = "SMS_R_System"
}
$newOtherThanQuery = Set-WmiInstance -class SMS_Query -arguments $OtherThanQueryHash -namespace $NAMESPACE
$newOtherThanQuery  | Format-List | Out-Null

$MoveOtherThanQuery=@{
InstanceKey = $newOtherThanQuery.QueryID;
ObjectType = 7;
ContainerNodeID = $QuerycontainerNodeID
}
Set-WmiInstance -Class SMS_ObjectContainerItem -arguments $MoveOtherThanQuery -namespace $NAMESPACE

# To Find Node: gwmi -Namespace $NAMESPACE -query "Select * from SMS_ObjectContainerNode WHERE Name = 'ContainerName'"
# Example run: JBMURPHY-SCCM-CreatePackage -XMLFilePath \\domain.local\DFSRoot\Path\Install.xml
#
}

PowerShell function to search CRM 2011 for and Entity (via REST/oData)

I wrote about how to retrieve records from CRM 2011 via oData. I wanted to wrap that up in a function that I can use to do a quick search:


Function JBMURPHY-CRM-SearchEntity{
PARAM([parameter(Mandatory=$true)][ValidateSet("Contact", "Account","SystemUser")]$EntityType,[parameter(Mandatory=$true)]$SearchString,[parameter(Mandatory=$true)]$SearchField,$FieldsToReturn)
$assembly = [Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$baseurl="http://crmserver.company.com/Organization/xrmservices/2011/OrganizationData.svc"
$urlparams="/$($EntityType)Set?`$filter=substringof('$($SearchString)',$($SearchField))"
$url=$baseurl+$urlparams
$Count=0
while ($url){
    $webclient = new-object System.Net.WebClient
    $webclient.UseDefaultCredentials = $true
    $webclient.Headers.Add("Accept", "application/json")
    $webclient.Headers.Add("Content-Type", "application/json; charset=utf-8");
    $dataString=$webclient.DownloadString($url)
    $json=new-object System.Web.Script.Serialization.JavaScriptSerializer
    $data=$json.DeserializeObject($dataString)
    foreach ($result in $data.d.results){
            $Count=$Count+1
            write-host -NoNewline "$Count. "
            foreach ($field in $FieldsToReturn){
            write-host -NoNewline "$field : "
            Write-Host -NoNewline $result."$field"
            Write-Host -NoNewline ", "
            #write-host "$($result.FullName) , $($result.EMailAddress1)"
            }
            Write-Host
    }
    if ($data.d.__next){
        $url=$data.d.__next.ToString()
    }
    else {
        $url=$null
    }
}
}

And to use this function:

JBMURPHY-CRM-SearchEntity -EntityType Account -SearchField Name -SearchString “Sard” -FieldsToReturn Name,AccountId

Using PowerShell to query CRM 2011 SOAP endpoint – Answer!

Big thanks to @JLattimer. He helped me figure our the error in my SOAP envelope.

In my last post, I was trying to retrieve FullName from Crm 2011’s web services via PowerShell. Below is the code to do that.

$xml = "<?xml version='1.0' encoding='utf-8'?>"
$xml += "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"
$xml += "<soap:Body>"
$xml += "<Retrieve xmlns='http://schemas.microsoft.com/xrm/2011/Contracts/Services'>"
$xml += "<entityName>contact</entityName>"
$xml += "<id>12345678-1234-1234-1234-123456789012</id>"
$xml += "<columnSet xmlns:q1='http://schemas.microsoft.com/xrm/2011/Contracts' xsi:type='q1:ColumnSet'>"
$xml += "<q1:Columns xmlns:c='http://schemas.microsoft.com/2003/10/Serialization/Arrays'>"
$xml += "<c:string>fullname</c:string>"
$xml += "<c:string>telephone1</c:string>"
$xml += "</q1:Columns>"
$xml += "</columnSet>"
$xml += "</Retrieve></soap:Body></soap:Envelope>"

$url="http://crmserver.company.com/Organization/XRMServices/2011/Organization.svc/web"

$http_request = New-Object -ComObject Msxml2.XMLHTTP
$http_request.Open('POST', $url, $false)
$http_request.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Retrieve");
$http_request.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
$http_request.setRequestHeader("Content-Length", $xml.length);
$http_request.send($xml);
$http_request.responseText
[ xml ]$results=$http_request.responseXML.xml
$ns = New-Object Xml.XmlNamespaceManager $results.NameTable
$ns.AddNamespace( "b", "http://schemas.microsoft.com/xrm/2011/Contracts" )
$ns.AddNamespace( "c", "http://schemas.datacontract.org/2004/07/System.Collections.Generic" )
$FullName=$results.selectSingleNode("//b:KeyValuePairOfstringanyType[c:key='fullname']/c:value/text()",$ns).Value
$Telephone=$results.selectSingleNode("//b:KeyValuePairOfstringanyType[c:key='telephone1']/c:value/text()",$ns).Value

Powered by WordPress. Designed by WooThemes