Dynamics CRM Export Solution (not on-premises) - powershell

I want to export a Dynamics CRM 365 solution. Tools like the ALM Toolkit e.g. didn't worked.
My Questions:
1) Is it possible to export the entire CRM365 solution by powershell at all?
2) If it is not possible by powershell - is it possible by c#?
I can connect to the crm withouth problems by powershell. But If I try to call
When I call this:
$domain = "https://mypath.com"
$username = "user"
$password = "password"
$secPassword = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secPassword.AppendChar($_)}
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secPassword
$conn = Get-CrmConnection -Url "https://mypath.com" -Credential $credentials
$exportPath = "C:\Users\xy\Data"
Import-Module "C:\Users\xy\Scripts\Adxstudio.Xrm.PowerShell\Adxstudio.Xrm.PowerShell.dll"
Export-CrmContent -Connection $conn -OutputPath $exportPath -Uncompressed -Generalized
I get the following error:
Export-CrmContent : Metadata Contains A Reference That Cannot Be Resolved: "https://mypath/XRMServices/2011/Organization.svc?wsdl=wsdl0".
In C:\Users\my.ps1:14 Char:1
+ Export-CrmContent -Connection $conn -OutputPath $exportPath -Uncompre ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Export-CrmContent], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Adxstudio.Xrm.PowerShell.Cmdlets.ExportCrmContent
But if I set up the $conn by using this:
$conn= Get-CrmConnection -OrganizationName MyOrg -DeploymentRegion MyRegion -OnLineType Office365 -Credential $credentials
I can get the organizations without problems. But when I try to call the export method with this connection I get:
The Parameter "$conn" cannot be bound. The value "Microsoft.Xrm.Tooling.Connector.CrmServiceClient" of the type "Microsoft.Xrm.Tooling.Connector.CrmServiceClient" can't be converted to "Adxstudio.Xrm.PowerShell.Cmdlets.PsCrmConnection".
Are there any ideas to solve one of the both problems to export the crm solution?

Not tried the Powershell approach, but I've achieved this using C# in the past.
static void ExportUnManagedSolutions(IOrganizationService service, String directory)
{
//Find all the solutions
QueryExpression query = new QueryExpression
{
EntityName = "solution",
ColumnSet = new ColumnSet("friendlyname", "uniquename", "version"),
Criteria = new FilterExpression()
{
Conditions =
{
//Unmanaged solutions only
new ConditionExpression("ismanaged", ConditionOperator.Equal, false),
//These are special CRM solutions, which are marked as unmanaged but cant actually be exported
new ConditionExpression("friendlyname", ConditionOperator.NotEqual, "Active Solution"),
new ConditionExpression("friendlyname", ConditionOperator.NotEqual, "Default Solution"),
new ConditionExpression("friendlyname", ConditionOperator.NotEqual, "Basic Solution"),
}
}
};
EntityCollection solutions = service.RetrieveMultiple(query);
//For each solution found
foreach (Entity s in solutions.Entities)
{
Console.WriteLine("Exporting " + s["friendlyname"]);
//Perform a solution export
ExportSolutionRequest request = new ExportSolutionRequest();
request.Managed = false;
request.SolutionName = (String)s["uniquename"];
ExportSolutionResponse response = (ExportSolutionResponse)service.Execute(request);
byte[] exportXml = response.ExportSolutionFile;
string filename = (String)s["uniquename"] + " " + (String)s["version"] + ".zip";
//This assumes the file directory already exists
File.WriteAllBytes(directory + filename, exportXml);
Console.WriteLine("Solution exported to {0}.", directory + filename);
}
}

Related

Change Credential Retrieval in SSRS with powershell

I want to change SSRS data source credential retrieval from using the following credentials to without any credentials with powershell and script fails.
I want to change value 'Store' to 'None' according to this article:
https://learn.microsoft.com/en-us/dotnet/api/reportservice2010.credentialretrievalenum?view=sqlserver-2016#ReportService2010_CredentialRetrievalEnum_None
This is my code:
$uri ='http://ServerName/ReportServer/ReportService2010.asmx?wsdl'
$reporting = New-WebServiceProxy -uri $uri -UseDefaultCredential -namespace "ReportingWebService"
$DataSources = $reporting.ListChildren('/', $true) | Where-Object {$_.Name -eq "DataSourceName"}
foreach($Object in $DataSources) {
$dataSource =$reporting.GetDataSourceContents($Object.path)
#$dataSource.CredentialRetrieval="None"
$dataSource.CredentialRetrieval=[ReportingWebService.CredentialRetrievalEnum]::None
$reporting.SetDataSourceContents($Object.path,$dataSource)
}
This is the error:
Exception calling "SetDataSourceContents" with "2" argument(s): "The combination of values for the fields UserName and CredentialRetrieval are not valid. --->
Microsoft.ReportingServices.Diagnostics.Utilities.InvalidElementCombinationException: The combination of values for the fields UserName and CredentialRetrieval are not valid."
At line:13 char:4
+ $reporting.SetDataSourceContents($Object.path,$dataSource)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SoapException
The issue was that i actually did not change existent credential retrieval settings 'Store' with required Username parameter.
To resolve it i should create new data source definition with new credential retrieval settings and apply it to my data source:
$uri ='http://servername/ReportServer/ReportService2010.asmx?wsdl'
$reporting = New-WebServiceProxy -uri $uri -UseDefaultCredential
$type=$reporting.GetType().Namespace
$DataSources = $reporting.ListChildren('/', $true) | Where-Object {$_.Name -eq "Data source name"}
foreach($Object in $DataSources) {
$dataSource =$reporting.GetDataSourceContents($Object.path)
$dataSourceDefinitionType = ($type + '.DataSourceDefinition');
$dataSourceDefinition = New-Object ($dataSourceDefinitionType);
$dataSourceDefinition.Extension = $dataSource.Extension; #get data from existent data source definition
$dataSourceDefinition.ConnectString = $dataSource.ConnectString #get data from existent data source definition
$credentialRetrievalDataType = ($type + '.CredentialRetrievalEnum');
$credentialRetrieval = new-object ($credentialRetrievalDataType);
$credentialRetrieval.value__ = 3;
$dataSourceDefinition.CredentialRetrieval = $credentialRetrieval;
$dataSourceDefinition.WindowsCredentials = $dataSource.WindowsCredentials; #get data from existent data source definition
$dataSourceDefinition.Enabled = $dataSource.Enabled; #get data from existent data source definition
$dataSourceDefinition.EnabledSpecified = $dataSource.EnabledSpecified; #get data from existent data source definition
$reporting.SetDataSourceContents($Object.path,$dataSourceDefinition)
}

System.Printing.Addjob() Error in Powershell

So I am trying to create a script that will take a print job from one paused print queue and add it to an active queue. However I am trying to utilize the AddJob() function and upon calling it with or without parameters it returns an exception and I am not sure why. Here is what I have so far
$host.Runspace.ThreadOptions = "ReuseThread"
Add-Type -AssemblyName System.Printing
$permissions = [System.Printing.PrintSystemDesiredAccess]::AdministrateServer
$queueperms = [System.Printing.PrintSystemDesiredAccess]::AdministratePrinter
$server = new-object System.Printing.PrintServer -argumentList $permissions
$queues = $server.GetPrintQueues(#([System.Printing.EnumeratedPrintQueueTypes]::Shared))
foreach ($q in $queues) {
if ($q.IsPaused -eq 1)
{
$qPaused = new-object System.Printing.PrintQueue -argumentList $server,$q.Name,1,$queueperms
}
else
{
$qPlaying = new-object System.Printing.PrintQueue -ArgumentList $server,$q.Name,2,$queueperms
}
}
$byteContents = #('This is a test')
$byteContents | Out-File -FilePath "C:\testinput.txt"
[byte[]]$bytes = Get-Content -Encoding byte -Path "C:\testinput.txt"
#$printJob = $qPaused.GetJob(3).
$qPlaying.AddJob()
$jobStream = $printJob.JobStream
$jobStream | Out-GridView
#$jobStream.Write($bytes, 0, $bytes.Length)
#$jobStream.Close()
What this gives me is an error at the $qPlaying.AddJob() saying
Exception calling "AddJob" with "0" argument(s): "Specified argument was out of the range of valid values.
Parameter name: clientPrintSchemaVersion"
At line:23 char:1
+ $qPlaying.AddJob()
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
Thank you for any feedback.
The version of the Print Schema is defined when you call the constructor for the queue in this line:
$qPlaying = new-object System.Printing.PrintQueue -ArgumentList $server,$q.Name,2,$queueperms
You are using PrintQueue Constructor (PrintServer, String, Int32, PrintSystemDesiredAccess) where the Int32 is the Print Queue Schema version. The MSDN article has a remark that: "The Print Schema version released with Windows Vista is "1"." Which would make sense that when you use 2 and receive an out of range error that 2 isn't an acceptable value.
You could use 1 as the value or use an alternate constructor. For example:
$qPlaying = new-object System.Printing.PrintQueue -ArgumentList $server,$q.Name,$queueperms

Create Folder in DocLib of a Teamsite - Office 365 - Sharepoint Online

I want to create an example folder in a Document Library of a created Teamsite on Sharepoint Online using Powershell but am running into an error.
After I have created the Teamsite I use the following script:
#Retrieve list
$DocLibName = "Dokumente"
$FolderTitle = "Beispiel"
$List = $ctx.Web.Lists.GetByTitle($DocLibName)
$folder = $list.AddItem("", [Microsoft.SharePoint.SPFileSystemObjectType]::Folder)
$folder["Title"] = $FolderTitle
$folder.Update();
$ctx.Load($List)
$ctx.ExecuteQuery()
Error Message
The type [Microsoft.SharePoint.SPFileSystemObjectType] was not found : Make sure that the assembly that contains this type is loaded.
Line:79 Char:1
+ $ Folder = $ List.addItem ("" [Microsoft.SharePoint.SPFileSystemObjectType ] :: Folde ...
It is not possible to use an index to a null array.
Line:80 Char:1
+ $ Folder ["Title"] = $FolderTitle
It is not possible to call a method for an expression of the NULL .
Line:81 Char:1
+ $Folder.Update();
How can this be resolved?
You are getting this error since Microsoft.SharePoint.SPFileSystemObjectTypetype belongs to SharePoint Server Side API which is not compatible with Office 365.
Below is demonstrated how to create a folder in SharePoint Online site via PowerShell (utilizes SharePoint CSOM API)
Function Create-Folder()
{
Param(
[Parameter(Mandatory=$True)]
[Microsoft.SharePoint.Client.Folder]$ParentFolder,
[Parameter(Mandatory=$True)]
[String]$FolderName
)
$folder = $ParentFolder.Folders.Add($folderName)
$ParentFolder.Context.Load($folder)
$ParentFolder.Context.ExecuteQuery()
return $folder
}
Function Get-Context($Url,$Username,$Password){
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$ctx.Credentials = $credentials
return $ctx
}
Usage
$Url = "https://contoso.sharepoint.com/"
$UserName = "jdoe#contoso.onmicrosoft.com"
$Password = ""
$TargetFolderName = "Archive2016"
$ctx = Get-Context -Url $Url -Username $Username -Password $Password
$parentFolder = $ctx.Web.Lists.GetByTitle("Documents").RootFolder
$folder = Create-Folder -ParentFolder $parentFolder -FolderName $TargetFolderName
Write-Host "Folder [$TargetFolderName] has been created succesfully. Url: $($folder.ServerRelativeUrl)"
For creating a folder hierarchy the following script could be utilized:
Function Create-FolderHierarchy()
{
Param(
[Parameter(Mandatory=$True)]
[Microsoft.SharePoint.Client.Folder]$ParentFolder,
[Parameter(Mandatory=$True)]
[String]$FolderUrl
)
$folderNames = $FolderUrl.Trim().Split("/",[System.StringSplitOptions]::RemoveEmptyEntries)
$folderName = $folderNames[0]
$curFolder = $ParentFolder.Folders.Add($folderName)
$ParentFolder.Context.Load($curFolder)
$ParentFolder.Context.ExecuteQuery()
if ($folderNames.Length -gt 1)
{
$curFolderUrl = [System.String]::Join("/", $folderNames, 1, $folderNames.Length - 1)
return Create-FolderHierarchy -ParentFolder $curFolder -FolderUrl $curFolderUrl
}
return $curFolder
}
If you are interested in scenario for uploading files while preserving a folder structure, take a look at How to: Upload files into Office 365 via PowerShell post, it contains ready made script for that purpose.

Copy Items Between Two EWS Servers - Powershell

I'm Trying to Get Into EWS, my Goal is to copy Data between Two Exchange Mailbox's in two different locations.
I'm Binding Two Inbox Folders, each in diffrent mailbox
Then i Get the items in the Source inbox folder and try to copy this items to the destination inbox folder, here's the code.
Add-Type -Path "C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
## Remote Connection ##
$MailboxName="User#Domain.com"
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1
$Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials("User","Password","Domain")
$exchService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
$exchService.Credentials = $Credentials
$exchService.Url = "https://Domain.com/EWS/Exchange.asmx"
## Bind Remote Inbox Folder
$FolderName="Inbox"
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::$FolderName,$MailboxName)
$MailFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchservice,$folderid)
## Local Connection ##
$LocalMailboxName = "LocalUser#Domain.local"
$LocalExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2
$LocalExchService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($LocalExchangeVersion)
$LocalExchService.UseDefaultCredentials = $true
$LocalExchService.AutodiscoverUrl($LocalMailboxName)
$LocalExchService.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $LocalMailboxName)
$LocalFolderName="Inbox"
$Localfolderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::$LocalFolderName,$LocalMailboxName)
$LocalMailFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($LocalExchService,$Localfolderid)
## Get the items of the source mailbox "Inbox"
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(100)
$fiItems = $exchservice.FindItems($MailFolder.id,$ivItemView)
## The Copy Section
foreach ($item in $fiItems)
{
$item.Copy($LocalMailFolder.Id)
}
Then I get This Error:
Exception calling "Copy" with "1" argument(s): "No mailbox with such guid."
At line:1 char:30
+ foreach ($item in $fiItems) {$item.Copy($LocalMailFolder.Id)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ServiceResponseException
Appreciate any help, Thanks
You cannot use copy to copy mails between Exchange Services, the error simply means that the remote service does not know the local folder id - because that folder(with that ID) does not exist on the remote service.
You need to load the item, create a NEW item in your local folder, copy all properties from the old item to the new one, then save the new item.
As I do not know Powershell, here a C# listing that should get you started, instead of:
foreach ($item in $fiItems)
{
$item.Copy($LocalMailFolder.Id)
}
->
foreach (var remoteItem in fiItems)
{
var localItem = new Item(LocalExchService);
localItem.Subject = remoteItem.Subject;
localItem.Body = remoteItem.Body;
// ... and so on. need to cast to the correct type, to access ALL properties, too.
localItem.Save(LocalMailFolder);
}

Create Multiple Document Sets from List

I need a document set create for every name in this SharePoint 2010 list. The Document set title is the first and last name of the person and the document set has committee name property that needs to be set as well. The committee name comes from the same SharePoint list.
I don't understand wrong with my code:
$ErrorActionPreference = "Stop"
$url = "http://SERVER/etest"
$listName = "Advisory Committee"
$doclib = "TACM Application Docments"
$web = Get-SPWeb $url;
$list = $web.Lists[$listName];
$item = $list.Items;
$item | ForEach-Object {
$fullName = $_['Last Name'] + ", " + $_['First Name']
$committeeName = $_['Committee Name']
$cType = $list.ContentTypes["Document Set"]
[Hashtable]$docsetProperties = #{"Committee Name"=$committeeName}
$newDocumentSet = [Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet]::Create($doclib.RootFolder,
$fullName,$cType.Id, $docsetProperties)
}
$web.Dispose()
I get the following error:
ForEach-Object : Cannot find an overload for "Create" and the argument count: "4".
At C:\Users\ev\desktop\docset.ps1:10 char:23
+ $item | ForEach-Object <<<< {
+ CategoryInfo : NotSpecified: (:) [ForEach-Object], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest,Microsoft.PowerShell
.Commands.ForEachObjectCommand
DocumentSet.Create method expects the first parameter to be a folder (SPFolder type):
parentFolder
Type: Microsoft.SharePoint.SPFolder
The folder in which to create the new DocumentSet object.
In your case you are passing an invalid object $doclib.RootFolder since $doclib is a string variable, probably you want something like this:
$doclibName = "TACM Application Docments"
$doclib = $web.Lists[$doclibName];
$newDocumentSet = [Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet]::Create($doclib.RootFolder,$fullName,$cType.Id, $docsetProperties)
Example
$url = "http://contoso.intranet.com"
$listTitle = "Documents"
$web = Get-SPWeb $url;
$list = $web.Lists[$listTitle]
$docSetContentType = $list.ContentTypes["Document Set"]
[Hashtable]$docSetProperties = #{}
$docSetName = "Archive"
$docSet = [Microsoft.Office.DocumentManagement.DocumentSets.DocumentSet]::Create($list.RootFolder,$docSetName,$docSetContentType.Id, $docSetProperties)
$web.Dispose()
How to add Document Set content type into library
Go to Library Settings, then click Advanced Settings
set Allow management of content types? to Yesand click Ok button
click Add from existing site content types link and select
Document Set content type, then click Ok button