PowerShell - Exception New-WebServiceProxy SOAP - web-services

When I execute my code, the following exception was thrown (German):
Ausnahme beim Aufrufen von "GetListItems" mit 7 Argument(en):
"Exception of type
'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown."
Is it possible to get more details about the Soap Server Exception?
My code:
$url = "http://mysharepoint.de/websites/test/"
$docBib = "TestDocLib"
$sitesWS = New-WebServiceProxy ($url + "_vti_bin/Lists.asmx") -UseDefaultCredential
$sitesWS.Proxy = New-Object System.Net.WebProxy("")
$xmlDoc = New-Object System.Xml.XmlDocument
$xmlDoc.LoadXml("<Document><Query /><ViewFields /><QueryOptions /></Document>")
$queryNode = $xmlDoc.SelectSingleNode("//Query")
$viewFieldsNode = $xmlDoc.SelectSingleNode("//ViewFields")
$queryOptionsNode = $xmlDoc.SelectSingleNode("//QueryOptions")
$queryNode.InnerXml = "<Where></Where>"
$sitesWS.GetList("test")
$result = $sitesWS.GetListItems($docBib, $null, $queryNode, $viewFieldsNode, $null, $queryOptionsNode, $null)

I've struggled with managing Sharepoint via web services as well. So I can tell how picky these can be with their arguments. This is how I set the GetListItems call up - and got it working:
$xmlDoc = new-object System.Xml.XmlDocument
$viewFields = $xmlDoc.CreateElement("ViewFields")
$queryOptions = $xmlDoc.CreateElement("QueryOptions")
$queryOptionsString = "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns><DateInUtc>TRUE</DateInUtc><ViewAttributes Scope='RecursiveAll' />"
$queryOptions.set_innerXML($queryOptionsString)
$query = $xmlDoc.CreateElement("Query")
$sitesWS = $service.GetListItems($docBib, "", $query, $viewFields, "", $queryOptions, "")
The trick, I think is that I create XML elements for each of $viewFields,$queryOptions and $query (but both viewFields and query can be empty except for their 'root' tags).

Related

List from user input in powershell getting replaced instead of appended

In my script, I the user to add values to a list that I will use for the rest of the script.
I'm currently using this:
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(350,380)
$form.Padding = New-Object System.Windows.Forms.Padding(20,100,20,20)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Multiline = $true
$textBox.ScrollBars = "Vertical"
$textBox.ReadOnly = $true
$textBox.Dock = [System.Windows.Forms.DockStyle]::Fill
$form.Controls.Add($textBox)
$inputLabel = New-Object System.Windows.Forms.Label
$inputLabel.Text = "Doc:"
$inputLabel.Size = New-Object System.Drawing.Size(50,20)
$inputLabel.Location = New-Object System.Drawing.Point(20,22)
$form.Controls.Add($inputLabel)
$addDocButton = New-Object System.Windows.Forms.Button
$addDocButton.Text = "Add to project"
$addDocButton.Size = New-Object System.Drawing.Size(85,23)
$addDocButton.Location = New-Object System.Drawing.Point(220,20)
$docs = #()
$addDocButton.Add_Click({
$docs += $inputBox.Text
$textBox.AppendText("Document added to project: $docs`r`n")
$inputBox.Clear()
})
$form.Controls.Add($addDocButton)
$inputBox = New-Object System.Windows.Forms.TextBox
$inputBox.Size = New-Object System.Drawing.Size(140,20)
$inputBox.Location = New-Object System.Drawing.Point(70,20)
$form.Controls.Add($inputBox)
$form.ShowDialog()
but the list is getting rewritten every time I click the button.
Shouldn't the "+=" be appending the values and not rewriting it?
If variable $docs is needed after the window has been closed, best define it as List object because that is optimized for adding and removing items as opposed to a static array.
When adding items to an array defined with #() using +=, the entire array needs to be rebuilt in memory, which is time and memory consuming
When an event handler scriptblock needs to address a variable defined outside the scriptblock, you need to scope it with $script:, otherwise the variable will be simply a new variable, local to the scriptblock.
$docs = [System.Collections.Generic.List[string]]::new()
$addDocButton.Add_Click({
if (![string]::IsNullOrWhiteSpace($inputBox.Text)) {
$str = $inputBox.Text.Trim()
# refer to the $docs object defined OUSIDE this scriptblock with $script: scoping
$script:docs.Add($str)
$textBox.AppendText("Document added to project: $str`r`n")
}
$inputBox.Clear()
})

How to populate Combobox with result of Powershell command

Can someone assist on how to fill a combobox with the result of a powershell command?
Im trying to fill a combobox with the result of a "Get" cmdlet but I only get some powershell parameters as result.
$ButtonCollectionSearch.Add_Click({
$name = $textboxlogonname.text
$ComboBox = New-Object System.Windows.Forms.ComboBox
$ComboBox.Width = 400
$Collections = Get-RDSessionCollection | fl -Property CollectionName
Foreach ($Collection in $Collection) {
$ComboBox.Items.Add($Collection);
}
$ComboBox.Location = New-Object System.Drawing.Point(120, 10)
$main_form.Controls.Add($ComboBox)
})
The reason you're getting formatting metadata is that you asked for formatting metadata - by piping all your data through fl (which is a alias for Format-List).
Since we just want the value of the CollectionName, use ForEach-Object -MemberName in place of fl -Property:
$Collections = Get-RDSessionCollection | ForEach-Object -MemberName CollectionName
You'll also want to address the typo in the foreach loop declaration - change:
Foreach ($Collection in $Collection) {
to:
Foreach ($Collection in $Collections) {

Vtiger CRM #: How to write PHP code in log4php.properties file

I am new to Vtiger CRM. I want to write php code in log4php.properties file and also it need to be executed.
I can write the code but it is not executing at all. So kindly help me with a way which will allow to execute the file.
Also this need to be executed dynamic with separate domains.
Thanks
Open your index.php file from crm root directory and Add this code
function replace_string_in_a_file($filepath, $search, $replace) {
if (#file_exists($filepath)) {
$file = file($filepath);
foreach ($file as $index => $string) {
if (strpos($string, $search) !== FALSE)
$file[$index] = "$replace\n";
}
$content = implode($file);
return $content;
}else {
return NULL;
}
}
$filepath = $root_directory . 'log4php.properties';
$search = 'log4php.appender.A1.File=';
$replace = 'log4php.appender.A1.File=' . DOMAIN_PATH . '/logs/vtigercrm.log';
$log_properties_content = replace_string_in_a_file($filepath, $search, $replace);
if (!empty($log_properties_content)) {
file_put_contents($filepath, $log_properties_content);
}

powershell script to call a list of variables to input into current script

So below is my script on how to call recursive members in groups across a trusted domain. what i need help with is to convert this from looking up a single group to multiple groups.
At the line $objGrp = [ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com" i have to manually change it to whatever group i want to search for. i instead want this script to call a text file with a list of groups.
for example, in the text file there would be
CN=Administrators,CN=Builtin,DC=domain,DC=com
CN=domain admins,CN=users,DC=domain,DC=com
CN=enterprise admins,CN=users,DC=domain,DC=com
what do i need to add/change to be able to do this?
# Script begins
#
# Bind to the AD group
$objGrp = [ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com"
#[ADSI]"LDAP://CN=Administrators,CN=Builtin,DC=domain,DC=com"
#
$Global:GroupMembers = #()
# Function to read the group members - nested members
Function GetGroupMember($objGrp)
{
# Enumerate the group members
foreach($member in $objGrp.member)
{
# Bind to the each user using DN
$strTemp = "LDAP://" + $member
$objTemp = [ADSI]$strTemp
# Check for AD Group object based on objectCategory
$strCat = [System.String]$objTemp.objectCategory
#foreign object
$res = $strCat.StartsWith("CN=Foreign-Security-Principal")
#$strCat
If($res -eq $True)
{
# bind to the foreign object
$strTemp = "LDAP://" + $member
$tempObj = [ADSI]$strTemp
# convert binary SID to bindable string SID
$objBin = $tempObj.objectSID.Item(0)
$objSID = New-Object System.Security.Principal.SecurityIdentifier($objBin,0)
$srchDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://dc=domain,dc=com")
$dirSrchObj = New-Object System.DirectoryServices.DirectorySearcher($srchDomain)
#$objSID.Value
[System.Environment]::NewLine
$dirSrchObj.Filter = "((objectSID=" + $objSID.Value + "))"
# Search scope to sub-level
$dirSrchObj.SearchScope = "Subtree"
$dirSrchObj.PageSize = 1
# Array of result collection - users
$srchResArr = $dirSrchObj.FindOne()
"======================================="
If ($srchResArr -ne $NULL)
{
# bind to the object
#$strTem = [System.String]$srchResArr.ToString()
$objEntry = $srchResArr.GetDirectoryEntry()
# read and compare the object category for group object
[System.String]$strTemp1 = $objEntry.objectcategory
$res1 = $strTemp1.StartsWith("CN=Group")
if($res1 -eq $True)
{
#enumerate the group members
Write-Host "The members of foreign group " $objEntry.Name "are: "
Foreach($obj in $objEntry.member)
{
$strTemp2 = "LDAP://" + $obj
$objTemp2 = [ADSI]$strTemp2
[System.String]$strTemp3 = $objTemp2.objectCategory
$res2 = $strTemp3.StartsWith("CN=Group")
if($res2 -eq $True)
{
GetGroupMember($objTemp2)
}
Else
{
$objTemp2.distinguishedName
$Global:GroupMembers += $objTemp2.distinguishedName
}
}
}
Else
{
"Foreign user object: "
$objEntry.distinguishedName
$Global:GroupMembers += $objEntry.distinguishedName
}
}
"======================================="
[System.Environment]::NewLine
}
Else
{
$flag = $strCat.StartsWith("CN=Group")
# If it is a Group object then call this method (recursive)
If($flag -eq $TRUE)
{
Write-Host "++++++++++++++++++++++Recursive Call to Enumerate" $objTemp.distinguishedName
GetGroupMember($objTemp)
Write-Host "---------------------- End Recursive Call to Enumerate" $objTemp.distinguishedName
}
# If user object then display its DN
if($flag -eq $False)
{
$objTemp.distinguishedName
$Global:GroupMembers += $objTemp.distinguishedName
#$objTemp.sAMAccountname
}
}
}
}
#
GetGroupMember $objGrp
""
""
"Final List:"
$Global:GroupMembers | sort -uniq | out-file c:\temp\test.csv
If your list of groups is in C:\grouplist.txt then you can use Get-Content to get the names, then loop through them:
$groupNames = Get-Content 'C:\grouplist.txt'
foreach($groupName in $groupNames)
{
GetGroupMember [ADSI]$groupName
}
"Final List:"
$Global:GroupMembers | sort -uniq | out-file c:\temp\test.csv

Trying to compare web service response and expected xml from file

We're developing in Java for the most, but we want to integration test (using https://github.com/scottmuc/Pester) our web-services with ms as well. To do this I'm writing powershell scripts that connects to a web-service and compares the response to xml that I've loaded from a file.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$instance = New-WebServiceProxy -Uri "https://localhost:7002/service?WSDL" -Namespace "myspace"
$instance.Credentials = new-object System.Net.NetworkCredential("user", "pass")
...
$reply = $instance.fetchInformation($inputA, $inputB)
[xml]$expected = Get-Content ("expected.xml")
...
However, now I have a $reply that contains objects from the myspace namespace and an $expected that contains an XMLNode. I see two ways I can do this (there are probably many more):
Get the original XML response and compare that. However, I can't seem to find out how to get that.
Serialise the $expected XML into the myspace namespace objects. Is that possible?
You could serialize the response returned by the web service to XML and compare it with the contents of the expected.xml file as strings.
Here's an example:
$writer = New-Object System.IO.StringWriter
$serializer = New-Object System.Xml.Serialization.XmlSerializer($reply.GetType())
$serializer.Serialize($writer, $reply)
$replyAsXml = $writer.ToString()
$expectedReplyAsXml = Get-Content expected.xml
$replyAsXml -eq $expectedReplyAsXml
Note that in this example you need to make sure that XML contained in the expected.xml file matches the one returned by the XmlSerializer also in regard to spacing and indenting. In order to avoid that, you could strip all extra characters (such as spaces and newlines) from the two strings before comparing them.
I ended up with a completely different approach. The two XML's was quite different from each other so instead I created a custom comparator. This made it possible for me to simply write custom code to ignore uninteresting differences.
This lead to some pile of crude code that does the job:
# Assume two arrays of equal length
Function Zip {
Param($a1, $a2)
$sum = New-Object object[] $a1.Count
For ($i = 0; $i -lt $a1.Count; ++$i) {
$sum[$i] = New-Object object[] 2
$sum[$i][0] = $a1[$i]
$sum[$i][1] = $a2[$i]
}
Return ,$sum
}
Function XmlChildNodes2List{
param($nodes)
$myArray = New-Object object[] 0
For ($i = 0; $i -lt $nodes.Count; ++$i) {
$node = $nodes.Item($i)
If ($node -ne $null) {
$myArray += $node
}
}
Return ,$myArray
}
Function ShowContext{
Param($ctx)
" at " + $ctx
}
Function CompareNode{
Param($o1, $o2, $ctx)
Try {
Switch ($o1.GetType().Name) {
"XmlDocument" {
CompareXml $o1.ChildNodes $o2.ChildNodes
}
"XmlChildNodes" {
$olist1 = XmlChildNodes2List $o1 | Sort
$olist2 = XmlChildNodes2List $o2 | Sort
If ($olist1.Count -ne $olist2.Count) {
$msg = "Unequal child node count " + ($olist1 -join ",") + " and " + ($olist2 -join ",") + (ShowContext $ctx)
throw $msg
} Else {
$list = Zip $olist1 $olist2
$value = $true
foreach ($item in $list) {
if ($value -eq $true) {
$value = CompareXml $item[0] $item[1] $ctx
}
}
$value
}
}
"XmlElement" {
If ($o1.LocalName -eq $o2.LocalName) {
If ($o1.LocalName -eq "uninterestingElement" -or $o1.LocalName -eq "uninterestingElement2") {
$true
} Else {
CompareXML $o1.ChildNodes $o2.ChildNodes ($ctx + "/" + $o1.LocalName)
}
} Else {
throw ("Element " + $o1.LocalName + " != " + $o2.LocalName + (ShowContext $ctx))
}
}
"XmlDeclaration" {
$true
}
"XmlText" {
$result = $o1.InnerText.Replace("`r`n","`n")
$expect = $o2.InnerText.Replace("`r`n","`n")
# TODO: Hack to remove timezone from expected dates in format 2005-09-01+02:00, the webservice side of the
# reply to xml-conversion looses them
If ($expect -match "^(\d{4}-\d\d-\d\d)\+\d\d:\d\d$") {
$expect = $Matches[1]
}
If ($result -eq $expect) {
$true
} Else {
throw ($o1.InnerText + " is not equal to " + $o2.InnerText + (ShowContext $ctx))
}
}
Default {
throw ("What to do with node " + $o1.GetType().Name + (ShowContext $ctx))
}
}
} Catch [Exception] {
throw $_
}
}
Function CompareXML{
Param($o1, $o2, $ctx)
If ($o1 -eq $null -and $o2 -eq $null) {
$true
} ElseIf ($o1 -eq $null -or $o2 -eq $null) {
throw ("Response or expected is null")
} ElseIf ($o1.GetType() -eq $o2.GetType()) {
CompareNode $o1 $o2 $ctx
} Else {
throw ($o1.GetType().Name + " is not " + $o2.GetType().Name + (ShowContext $ctx))
}
}
This can then be run on two XML's like this:
CompareXML $result $expected ""