Tag Archives | PowerShell

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

Using PowerShell to query CRM 2011 SOAP endpoint – help!

I don’t know what I am doing wrong. All I am trying to do is to query  CRM 2011 via PowerShell and SOAP. The following PowerShell script should return the Contact’s full name, but I get nothing. Any ideas??

Here is the PowerShell:

$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:Attributes>"
$xml += "<q1:Attribute>fullname</q1:Attribute>"
$xml += "<q1:Attribute>telephone1</q1:Attribute>"
$xml += "</q1:Attributes>"
$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

And here is the response:

$http_request.responseText

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body><RetrieveResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
<RetrieveResult xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Attributes xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<a:KeyValuePairOfstringanyType>
<b:key>accountid</b:key>
<b:value i:type="c:guid" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/">12345678-1234-1234-1234-123456789012</b:value>
</a:KeyValuePairOfstringanyType>
</a:Attributes>
<a:EntityState i:nil="true"/><a:FormattedValues xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic"/>
<a:Id>12345678-1234-1234-1234-123456789012</a:Id><a:LogicalName>account</a:LogicalName>
<a:RelatedEntities xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic"/>
</RetrieveResult>
</RetrieveResponse>

I just don’t know what I am doing wrong. Why won’t the code return “fullname”, it is in the columnSet.

Update-2012-05-08:I have posted my question here, no answer yet

Update2-2012-05-05: I have posted and received and answer here on stack overflow. Big thanks to @JLattimer

PowerShell script to copy a SharePoint Document Library to a Local Path

I wanted to have a PowerShell script that downloaded A Document Library’s contents to a local folder. This is what I put together.

Function JBM-SharePoint-CopyDocumentLibraryLocal {
PARAM([Parameter(Mandatory=$true)]$SiteURL,
    [Parameter(Mandatory=$true)]$DocumentLibrary,
    [Parameter(Mandatory=$true)]$Destination)
$spWeb = Get-SPWeb -Identity http://$SiteURL
$list = $spWeb.Lists[$DocumentLibrary]
foreach ($listItem in $list.Items)
{
    $DestinationPath = $listItem.Url.replace("$DocumentLibrary","$Destination").Replace("/","\")
    write-host "Downloading $($listItem.Name) -> $DestinationPath"

    if (!(Test-Path -path $(Split-Path $DestinationPath -parent)))
    {
        write-host "Createing $(Split-Path $DestinationPath -parent)"
        $dest = New-Item $(Split-Path $DestinationPath -parent) -type directory
    }
    $binary=$spWeb.GetFile($listItem.Url).OpenBinary()
    $stream = New-Object System.IO.FileStream($DestinationPath), Create
    $writer = New-Object System.IO.BinaryWriter($stream)
    $writer.write($binary)
    $writer.Close()
}
$spWeb.Dispose()

Add an appointment/email/phone activity to CRM 2011 via PowerShell (REST/oDATA)

I am looking to move some older list data into CRM 2011, so I wanted a way to create some “activities” via powershell. Below is the code to do that. In the first part of the code, I create a PowerShell object and then I convert it to a JSON object via PowerShell 3’s new ConvertTo-JSON cmdlet.

$JsonObject = New-Object psobject -Property @{
ActivityTypeCode = "appointment"
Subject = "jbmurphy TEST"
Description = "This is a descritpion"
ScheduledStart = "2012-03-20T18:00:00Z"
ScheduledEnd = "2012-03-20T18:00:00Z"
Location = "Office"
}

# I am using PowerShell 3's ConvertTo-Json
$jsonEntity=$JsonObject | ConvertTo-Json
#$url="http://crmserver.company.com/OrgName/xrmservices/2011/OrganizationData.svc/EmailSet"
#$url="http://crmserver.company.com/OrgName/xrmservices/2011/OrganizationData.svc/PhoneCallSet"
$url="http://crmserver.company.com/OrgName/xrmservices/2011/OrganizationData.svc/AppointmentSet"

$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($jsonEntity)
$http_request.statusText

PowerShell script to search SharePoint Search WebService via SOAP

I wanted to copy all the files found in a SharePoint Search result for a scope that lived on a file share. So I wrote the following PowerShell code to query a SharePoint Search scope and find the url for each result.

#$KeywordQuery="Cows"
$SQLQuery="SELECT WorkId,Path,Title,Write,Author from Scope() WHERE `"Scope`"='NarrowScope' AND FREETEXT(defaultproperties,'Cows')"

$CountToReturn = 1000
$xmlDoc = new-object System.Xml.XmlDocument
$QueryPacket = $xmlDoc.CreateElement("QueryPacket")
$QueryPacket.SetAttribute("xmlns", "urn:Microsoft.Search.Query")
$Query = $xmlDoc.CreateElement("Query")
[void]$querypacket.AppendChild($Query)
$Context = $xmlDoc.CreateElement("Context")
[void]$query.AppendChild($Context)
$QueryText = $xmlDoc.CreateElement("QueryText")

#If you are Using the KeyWord method
#$QueryText.SetAttribute("type", "string") 
#$QueryText.set_InnerXMl($KeywordQuery)

#IF you are using SQL method
$QueryText.SetAttribute("type", "MSSQLFT")
$QueryText.set_InnerXMl($SQLQuery)

[void]$context.AppendChild($QueryText)
$Range = $xmlDoc.CreateElement("Range")
[void]$query.AppendChild($Range)
$Count = $xmlDoc.CreateElement("Count")
$Count.set_InnerXMl($CountToReturn)
[void]$range.AppendChild($Count)

$IncludeSpecialTermResults=$xmlDoc.CreateElement("IncludeSpecialTermResults")
$IncludeSpecialTermResults.set_InnerXML("false")
[void]$query.AppendChild($IncludeSpecialTermResults)

$PreQuerySuggestions=$xmlDoc.CreateElement("PreQuerySuggestions")
$PreQuerySuggestions.set_InnerXML("false")
[void]$query.AppendChild($PreQuerySuggestions)

$HighlightQuerySuggestions=$xmlDoc.CreateElement("HighlightQuerySuggestions")
$HighlightQuerySuggestions.set_InnerXML("false")
[void]$query.AppendChild($HighlightQuerySuggestions)

$IncludeRelevantResults=$xmlDoc.CreateElement("IncludeRelevantResults")
$IncludeRelevantResults.set_InnerXML("false")
[void]$query.AppendChild($IncludeRelevantResults)

$IncludeHighConfidenceResults=$xmlDoc.CreateElement("IncludeHighConfidenceResults")
$IncludeHighConfidenceResults.set_InnerXML("false")
[void]$query.AppendChild($IncludeHighConfidenceResults)

$Service = New-WebServiceProxy -UseDefaultCredential -uri http://sharepoint.search.com/Search/_vti_bin/Search.asmx
[ xml ]$Results = $Service.Query($QueryPacket.OuterXml)
write-host "Results=$($Results.ResponsePacket.Response.Range.Count)"
foreach ($Doc in $Results.ResponsePacket.Response.Range.Results.Document){
$PATH=$($Doc.Action.LinkUrl.("#text")).Replace("/","\").Replace("file:","")
write-host $PATH
#here is where you put your copy cmd
cp $PATH c:\Temp
}

PowerShell how to create an object (Note to Self)

$test = new-object psobject -Property @{
Name = 'John Doe'
Age = 3
Amount = 10.1
MixedItems = (1,2,3,"a")
NumericItems = (1,2,3)
StringItems = ("a","b","c")
}

Another example:

$Object = New-Object PSObject -Property @{
        LineNumber       = $LineNumber
        Date             = $TodayDate
        ServerName       = $svr
        DatabaseName     = $Database
        UserName         = $user.name
        CreateDate       = $CreateDate
        DateLastModified = $DateLastModified
        AsymMetricKey    = $user.AsymMetricKey
        DefaultSchema    = $user.DefaultSchema
        HasDBAccess      = $user.HasDBAccess
        ID               = $user.ID
        LoginType        = $user.LoginType
        Login            = $user.Login
        Orphan           = ($user.Login -eq "")
    }

Second example taken from here

PowerShell to get all items in a SharePoint 2007 list via Web Services/SOAP

I wanted to get a list’s contents in a SharePoint 2007 site via PowerShell. I ran into only one issue – how to handle the pagination. When creating the Xml to include the next page, I was running into formatting issues because the text contained a “=”. This link suggested that I create the XML element first then add the innerText after. Worked after that!

TheBelow is my script to get the contents of a SharePoint 2007 list.

 

$listName = "List Name"
$xmlDoc = new-object System.Xml.XmlDocument
$query = $xmlDoc.CreateElement("Query")
$viewFields = $xmlDoc.CreateElement("ViewFields")
$queryOptions = $xmlDoc.CreateElement("QueryOptions")
$rowLimit = "50"
$service = New-WebServiceProxy -UseDefaultCredential -uri http://sharepoint2007.comapny.com/_vti_bin/lists.asmx?WSDL
$nextPage=$true
while($nextPage){
$list = $service.GetListItems($listName, "", $query, $viewFields, $rowLimit, $queryOptions, "")
$list.data.row | select ows_ID,ows_Created,ows_Title
if ($list.data.ListItemCollectionPositionNext){
$nextPage=@"
<Paging ListItemCollectionPositionNext="" />
"@
$queryOptions.set_InnerXml($nextPage)
$queryOptions.ChildNodes[0].Attributes["ListItemCollectionPositionNext"].InnerText = "$($list.data.ListItemCollectionPositionNext)"
}
else {
write-host "done"
$nextPage=$false
}
}

PowerShell: redirect (System.Xml.XmlDocument).Save() to console

I saw the code below somewhere, and could not remember how to do it later when I needed it. System.Xml.XmlDocument has a built in method to save the document to a file. I wanted to simulate that, but redirect it to the console. I finally found the code how to do it.

$xml = new-object System.Xml.XmlDocument
$xml.Save([Console]::Out)

Now I know where to look to remind myself.

Powered by WordPress. Designed by WooThemes