I am creating a WPF UI and I am having trouble getting the output from a foreach loop within a function into a WPF textbox. The variables I need to output ar $id $newValue and $serviceName
#Iteration through services perform string replacement
ForEach ($Response in $Responses ) {
$id = $Response.id
$newValue = $Response.value.Replace("\Service", "")
$serviceName = $Response.serviceName
Write-Output $id
Write-Output $serviceName
Write-Output $newValue
#if statement here for testing this should be removed
if ($id -eq ) {
$Payload = #{
hostName = '';
hostOperatingSystem = 0;
optionalFilter1 = '';
optionalFilter2 = '';
description = '';
serviceName = $serviceName;
sectionName = "Services";
signature = 'null';``
value = $newValue
} | ConvertTo-Json -Depth 10
#Service Configuration API PUT method call to update fullpath value
$newURI = $URI + '/' + $id
$Response = Invoke-RestMethod -Uri $newURI -Method PUT -Headers $Headers -Body $Payload -ContentType 'application/json'
}
#here for testing this should be removed
else {
$output.text = "Nothing to do"
}
}
$output.text = "Done!"
}
[xml]$Form = Get-Content "MainWindow.xaml"
$NR = (New-Object System.Xml.XmlNodeReader $Form)
$Win = [Windows.Markup.XamlReader]::Load($NR)
$URL = $win.FindName("URL")
$cid = $win.FindName("Client_ID")
$csecret = $win.FindName("Client_Secret")
$update = $Win.FindName("Update")
$output = $Win.FindName("output")
$update.Add_Click( {
$UserAuthRoute = $URL.text
$client_id = $cid.text
$client_secret = $csecret.text
if ($UserAuthRoute -eq "" -or $client_secret -eq "" -or $client_secret -eq "") {
[System.Windows.MessageBox]::Show("Please enter in all values","Variables Required")
}else{
UpdateServices $UserAuthRoute $client_id $client_secret
$output.text += "Service ID:"+$id , "Service Name: "+$serviceName, "$newValue"
}
})
$Win.ShowDialog() ```
The solution was to append the value and separate with a newline
$output.text += "Service ID: " + $id + "`r`n" + "Service Name: " + $serviceName + "`r`n" + "Service Value: " + $newValue + "`r`n"
Related
I have a need to run PowerShell scripts from C# application. I like using method AddScript for this. And it works quite nice. However, it does not seem to work as expected when I added parameters to script with method AddParameters.
Here is test payload (PowerShell):
param ([string]$Arg1, [string]$Arg2, [switch]$ArgParamless)
$filename = "payload_with_params.txt"
$filepath = $env:temp
$fullpath = Join-Path -Path $filepath -ChildPath $filename
$dt = Get-Date -Format "yyyy.MM.dd HH:mm:ss"
$val = $dt+' '+$Arg1+' '+$Arg2+' '+$ArgParamless
Add-Content -Path $fullpath -Value "$val"
It works just fine if I push it from PS like this:
.\payload_with_params.ps1 -Arg1 "Bla 1" -Arg2 "Bla 2" -ArgParamless
Result:
2023.01.19 16:58:10 Bla 1 Bla 2 True
The C# code (oversimplified):
string command = File.ReadAllText(pathToPS1);
List<CommandParameter> paramList = new List<CommandParameter>();
paramList.Add(new CommandParameter("Arg1", "Bla 1"));
paramList.Add(new CommandParameter("Arg2", "Bla 2"));
paramList.Add(new CommandParameter("ArgParamless"));
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
ps.AddParameters(paramList);
}
}
//Launching
ps.Invoke();
}
And the result:
2023.01.19 16:54:00 System.Management.Automation.Runspaces.CommandParameter System.Management.Automation.Runspaces.CommandParameter False
So.. it's not working as I expected. How should I supply parameters to script?
For [switch] parameters, you'll want to bind a bool - PowerShell will interpret true as "Present" and false as "Absent":
paramList.Add(new CommandParameter("ArgParamless", true));
Well, it turns out AddParameter(CommandParameter) approach doesn't work.
This approach is working:
string command = File.ReadAllText(pathToPS1);
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
ps.AddArgument("-Arg1 XXXXXX");
}
}
//Launching
ps.Invoke();
}
On PowerShell end this arguments can be extracted for usage from $args array:
$arglist = $args -join " "
Even better approach using hashtable:
string command = File.ReadAllText(pathToPS1);
using (PowerShell ps = PowerShell.Create())
{
//Adding script file content to object
ps.AddScript(command);
if (paramList != null)
{
if (paramList.Count > 0)
{
//Adding Params to object;
var hashtable = new Hashtable {
{ "Arg1", "XXXXXX" },
{ "Arg2", "YYYYYY" },
{ "ArgParamless", true }
};
ps.AddArgument(hashtable);
}
}
//Launching
ps.Invoke();
}
And that's what you do on PS side to use it:
function Wrapper-Test ([string]$Arg1, [string]$Arg2, [switch]$ArgParamless) {
$Result = $Args1+' '+$Args2+' '+$ArgParamless
return $Result
}
$MyArgs = "";
$MyArg = $args[0]
$MyArgs = Wrapper-Test #MyArg;
$filename = "payload_with_params.txt"
$filepath = $env:temp
$fullpath = Join-Path -Path $filepath -ChildPath $filename
$dt = Get-Date -Format "yyyy.MM.dd HH:mm:ss"
$arglist = $args -join " "
$val = $dt + " " + $MyArgs
Add-Content -Path $fullpath -Value "$val"
I created a script in C# and for personnal reasons, I would like to convert it in PowerShell.
After many tries, I still can't understand why it still gave me this error, is there something wrong with the code ?
"Cannot call a method in a Null expression." | when I call $reader.ReadLine()
This script goals is to read a .log file, and to find the usefull information to send them into MongoDB database.
C#
string level = "", username = "", date = "", solutionName = "", message = "";
FileStream logFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader reader = new StreamReader(logFileStream);
int compteur = 0;
while (compteur < lineCount-1)
{
bool info = true;
string messagelog = "";
int tmpCompteur = 0;
// open the file to read it
reader = File.OpenText(filePath);
// take the log message (could be multiple lines)
for (int i = 0; i < lineCount; i++)
{
string line = reader.ReadLine();
if (Regex.IsMatch(line, "INFO") || Regex.IsMatch(line, "ERROR"))
{
if (info)
info = !info;
else
break;
}
messagelog += line;
tmpCompteur++;
compteur++;
}
// Regex to find the log Level, UserName, Date, SolutionName, Message
if (Regex.IsMatch(messagelog, "INFO") || Regex.IsMatch(messagelog, "ERROR"))
level = Regex.Match(messagelog, "INFO").Value;
if (Regex.IsMatch(messagelog, "-(.*?)-"))
username = Regex.Match(messagelog, "-(.*?)-").Value.Substring(1, Regex.Match(messagelog, "-(.*?)-").Value.Length - 2);
if (Regex.IsMatch(messagelog, "([1-9]|([012][0-9])|(3[01]))\\/([0]{0,1}[1-9]|1[012])\\/\\d\\d\\d\\d [012]{0,1}[0-9]:[0-6][0-9]:[0-6][0-9]"))
date = Regex.Match(messagelog, "([1-9]|([012][0-9])|(3[01]))\\/([0]{0,1}[1-9]|1[012])\\/\\d\\d\\d\\d [012]{0,1}[0-9]:[0-6][0-9]:[0-6][0-9]").Value;
if (Regex.IsMatch(messagelog, "\\[E(.*?)\\]"))
solutionName = Regex.Match(messagelog, "\\[E(.*?)\\]").Value;
if (Regex.IsMatch(messagelog, "\\]\\s.*"))
message = Regex.Match(messagelog, "\\]\\s.*").Value.Substring(2);
// close the reader because we don't need it anymore
reader.Close();
// convert our data to an object to send it to MongoDB
var Data = new BsonDocument
{
{ "Date", DateTime.ParseExact(date, "dd/MM/yyyy HH:mm:ss", null) },
{ "Level", level},
{ "Message", message},
{ "UserName", username}
};
// send data to MongoDB
collection.InsertOneAsync(Data);
// delete the lines already processed by our programm
File.WriteAllLines(filePath, File.ReadAllLines(filePath).Skip(tmpCompteur).ToArray());
}
// close the fileStream
logFileStream.Close();
// delete the file
File.Delete(filePath);
}
PowerShell
[string]$level
[string]$userName
[string]$date
[string]$solutionName
[string]$message
$logFileStream = New-Object System.IO.FileStream $filePath, ([System.IO.FileMode]::Append), ([System.IO.FileAccess]::Write), ([System.IO.FileShare]::Read)
$reader = New-Object System.IO.StreamReader $logFileStream
# https://github.com/nightroman/Mdbc
Connect-Mdbc -ConnectionString $iniContent["MongoDB"]["Server"] -DatabaseName $iniContent["MongoDB"]["Database"] -CollectionName $iniContent["MongoDB"]["Collection"]
$pbar_LoadFile.Visible = $true
[int]$compteur = 0
while ($compteur -clt $linesCount) {
[bool]$info = $true
[string]$messageLog = ""
[int]$tmpCompteur = 0
$reader = $IOFile::OpenText($filePath)
for ([int]$i = 0; $i -lt $linesCount; $i++) {
$line = $reader.ReadLine()
if ($line -match "INFO") {
if ($info -eq $true) {
$info = $false
}
else {
break
}
}
$messageLog += $line
$tmpCompteur++
$compteur++
}
if ($messageLog -match "INFO") {
$level = $matches[0]
}
if ($messageLog -match "-(.*?)-") {
$userName = $matches[0].Substring(1, $matches[0].length - 2)
}
if ($messageLog -match "([1-9]|([012][0-9])|(3[01]))\/([0]{0,1}[1-9]|1[012])\/\d\d\d\d [012]{0,1}[0-9]:[0-6][0-9]:[0-6][0-9]") {
$date = $matches[0]
}
if ($messageLog -match " ") {
$solutionName = $matches[0]
}
if ($messageLog -match "\]\s.*") {
$message = $matches[0].Substring(2)
}
$reader.Close()
#{Date = Convert-ToDateTime($date); Level = $level; Message = $message; UserName = $userName } | Add-MdbcData
(Get-Content $filePath | Select-Object -Skip $tmpCompteur) | Set-Content $filePath
}
$logFileStream.Close()
Remove-Item $filePath
$pbar_LoadFile.Value += 1
}
You are misunderstanding System.IO.StreamReader as $IOFile. You have to first declare it inside the $reader like this:
$reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $filePath
In powershell .NET Types are called like this:
[System.IO.File]
Their static methods are called by placing two colons after ].
EDIT: Problem was parameters.ToString(). Also like Lengning Liu pointed out you need to add '/sprocs/sprocname'
I'm trying to execute a stored procedure in Azure DocumentDB with a REST call in ASP.NET Core 1.0 / C#.
I use the method on this MSDN page to generate the hash:
https://msdn.microsoft.com/library/azure/dn783368.aspx
I'm getting a 401 Unauthorized repsonse. Is "sprocs" the right document type, or do i have to enter a different type?
public class Database
{
public async Task<HttpResponseMessage> StoredProcedure(string database, string collection, string storedProcedure, string[] parameters)
{
//https://{databaseaccount}.documents.azure.com/dbs/{db-id}/colls/{coll-id}/sprocs/{sproc-name}
string resourceLink = $"dbs/{database}/colls/{collection}";
var client = Client("POST", resourceLink, "sprocs");
StringContent content = new StringContent(parameters.ToString(), null, "application/query+json");
var uri = new Uri(_endpointUri, $"dbs/{database}/colls/{collection}/sprocs/{storedProcedure}");
HttpResponseMessage response = await client.PostAsync(uri, content);
return response;
}
private HttpClient Client(string verb, string resourceLink, string resourceType)
{
var client = new HttpClient();
var utc_date = DateTime.UtcNow.ToString("r");
client.DefaultRequestHeaders.Add("x-ms-date", utc_date);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-16");
client.DefaultRequestHeaders.Add("x-ms-max-item-count", "10000");
var authHeader = GenerateMasterKeyAuthorizationSignature(utc_date, verb, resourceLink, resourceType, _authorizationKey, "master", "1.0");
client.DefaultRequestHeaders.Add("authorization", authHeader);
return client;
}
private static string GenerateMasterKeyAuthorizationSignature(string utc_date, string verb, string resourceId, string resourceType, string key, string keyType, string tokenVersion)
{
var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
verb.ToLowerInvariant(),
resourceType.ToLowerInvariant(),
resourceId,
utc_date.ToLowerInvariant(),
""
);
byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);
return System.Net.WebUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
keyType,
tokenVersion,
signature));
}
}
it seems that when you generated the auth token, in the resourceId part, you left out "/sprocs/{storedProcedure}". You have included it in the uri, which is correct.
I am attaching a sample powershell script that, hopefully, will also help you to see how auth token is generated.
Add-Type -AssemblyName System.Web
$accountName = "<db account name>"
$connectionKey = "<secret key>"
$collectionName = "<coll name>"
$databaseName = "<db name>"
Write-host ("Account " + $accountName)
Write-host ("Database " + $databaseName)
Write-host ("Collection " + $collectionName)
function GetKey([System.String]$Verb = '',[System.String]$ResourceId = '',
[System.String]$ResourceType = '',[System.String]$Date = '',[System.String]$masterKey = '') {
$keyBytes = [System.Convert]::FromBase64String($masterKey)
$text = #($Verb.ToLowerInvariant() + "`n" + $ResourceType.ToLowerInvariant() + "`n" + $ResourceId + "`n" + $Date.ToLowerInvariant() + "`n" + "" + "`n")
$body =[Text.Encoding]::UTF8.GetBytes($text)
$hmacsha = new-object -TypeName System.Security.Cryptography.HMACSHA256 -ArgumentList (,$keyBytes)
$hash = $hmacsha.ComputeHash($body)
$signature = [System.Convert]::ToBase64String($hash)
Write-Host($text)
[System.Web.HttpUtility]::UrlEncode($('type=master&ver=1.0&sig=' + $signature))
}
function GetUTDate() {
$date = get-date
$date = $date.ToUniversalTime();
return $date.ToString("r", [System.Globalization.CultureInfo]::InvariantCulture);
}
function GetDatabases() {
$uri = $rootUri + "/dbs"
$hdr = BuildHeaders -resType dbs
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $hdr
$response.Databases
Write-Host ("Found " + $Response.Databases.Count + " Database(s)")
}
function GetCollections([string]$dbname){
$uri = $rootUri + "/" + $dbname + "/colls"
$headers = BuildHeaders -resType colls -resourceId $dbname
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
$response.DocumentCollections
Write-Host ("Found " + $Response.DocumentCollections.Count + " DocumentCollection(s)")
}
function BuildHeaders([string]$action = "get",[string]$resType, [string]$resourceId){
$authz = GetKey -Verb $action -ResourceType $resType -ResourceId $resourceId -Date $apiDate -masterKey $connectionKey
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", $authz)
$headers.Add("x-ms-version", '2015-12-16')
$headers.Add("x-ms-date", $apiDate)
$headers
}
function PostDocument([string]$document, [string]$dbname, [string]$collection){
$collName = "dbs/"+$dbname+"/colls/" + $collection
$headers = BuildHeaders -action Post -resType docs -resourceId $collName
$headers.Add("x-ms-documentdb-is-upsert", "true")
$uri = $rootUri + "/" + $collName + "/docs"
Write-host ("Calling " + $uri)
$response = Invoke-RestMethod $uri -Method Post -Body $json -ContentType 'application/json' -Headers $headers
$response
}
function PostSprocQuery([string]$dbname, [string]$collection){
$sprocName = "dbs/"+$dbname+"/colls/" + $collection + "/sprocs/samplesproc"
$headers = BuildHeaders -action Post -resType sprocs -resourceId $sprocName
$uri = $rootUri + "/" + $sprocName
Write-host ("Calling " + $uri)
write-host $authz
write-host $apiDate
$response = Invoke-RestMethod $uri -Method Post -Body $json -ContentType 'application/json' -Headers $headers
$response
}
$rootUri = "https://" + $accountName + ".documents.azure.com"
write-host ("Root URI is " + $rootUri)
#validate arguments
$apiDate = GetUTDate
$db = GetDatabases | where { $_.id -eq $databaseName }
if ($db -eq $null) {
write-error "Could not find database in account"
return
}
$dbname = "dbs/" + $databaseName
$collection = GetCollections -dbname $dbname | where { $_.id -eq $collectionName }
if($collection -eq $null){
write-error "Could not find collection in database"
return
}
$json = #"
{
"id": "3"
}
"#
PostDocument -document $json -dbname $databaseName -collection $collectionName
$json = #"
[
"samplesproc"
]
"#
PostSprocQuery -document $json -dbname $databaseName -collection $collectionName
Hello stackoverflow friends!
I have a Powershell script I'm working on where I am trying to do the following:
Select an Excel xlsx file with existing worksheets with headers only
Select a text file
Create a temporary CSV file from the text file and add headers to match the Excel file
Copy the information from the CSV file into a worksheet in the Excel file
Save/Quit
I've got everything I need working up to using the Range aspects of the Excel objects. When attempting to Copy data from the CSV file instantiated as a COM object, then Activating the xlsx file, I am getting an error stating
Exception calling "Paste" with "1" argument(s): "Paste method of
Worksheet class failed" At line:1 char:1
$Script:ExcelWorkSheet.Paste($tempRange)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : ComMethodTargetInvocation
Below is my code thus far. Any help whatsoever would be gratefully appreciated, as I'm at a loss:
BEGIN
{
Function Set-ScriptVars()
{
Add-Type -AssemblyName System.Windows.Forms
}
Function Select-File($FileType)
{
## Select file via selection dialog
do {
if($FileType -eq "xlsx")
{
Write-Host "`nPlease select the Excel file to import in the dialog"
}
elseif($FileType -eq "txt")
{
Write-Host "`nPlease select the Prescan or Postscan text file to import in the dialog"
}
Start-Sleep -Seconds 1
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{InitialDirectory = [Environment]::GetFolderPath('Desktop')}
[void]$FileBrowser.ShowDialog()
Write-Host "`nFile selected: " -NoNewline
Write-Host $FileBrowser.FileNames -ForegroundColor Yellow
$FileName = $FileBrowser.FileName
if ($FileName.EndsWith(".$FileType"))
{
$selectionValid = $True
}
else
{
Write-Host "The file selected is not a .$FileType file."
Write-Host "Restarting file selection loop."
$selectionValid = $False
}
} until ($selectionValid -eq $True)
if($FileType -eq "txt")
{
$Script:TextFile = $FileName
$Script:TextParentPath = (Get-Item $FileName).Directory.FullName
}
elseif($FileType -eq "xlsx")
{
$Script:ExcelFile = $FileName
$Script:ExcelParentPath = (Get-Item $FileName).Directory.FullName
}
}
Function Open-Excel($Sheet)
{
$ActiveSheet = $Sheet
$ExcelPath = $Script:ExcelFile
$Script:Excel = New-Object -ComObject Excel.Application
$Script:Excel.Visible = $True
$Script:Excel.UserControl = $False
$Script:Excel.Interactive = $False
$Script:Excel.DisplayAlerts = $False
$Script:ExcelWorkBook = $Script:Excel.Workbooks.Open($ExcelPath)
$Script:ExcelWorkSheet = $Script:Excel.WorkSheets.item($ActiveSheet)
$Script:ExcelWorkSheet.Activate()
}
Function Get-TextContent()
{
$Script:TextContent = Get-Content $Script:TextFile
}
Function Copy-TextData()
{
# create a random file name
$randomInt = #(0001..9999) | Get-Random
$tempCSV = Import-CSV $Script:TextFile -Header "Server","Role","Type","Object","Path"
$tempCSV | Export-CSV -Path $ENV:USERPROFILE\Desktop\tempCSV_$randomInt.csv -NoTypeInformation
$tempCSVPath = "$ENV:USERPROFILE\Desktop\tempCSV_$randomInt.csv"
$tempCSVName = "tempCSV_$randomInt"
# create a temporary file to copy from
$TempExcel = New-Object -ComObject Excel.Application
$TempExcel.Visible = $True
$TempWorkBook = $TempExcel.WorkBooks.Open($tempCSVPath)
$TempWorkSheet = $TempWorkBook.WorkSheets.Item($tempCSVName)
$tempRange = $TempWorkSheet.Range("A2:E2").UsedRange
$tempRange.Copy() | Out-Null
$Script:ExcelWorkSheet.Activate()
$Script:ExcelWorkSheet.Range("A2:E2").EntireColumn
$Script:ExcelWorkSheet.Paste($tempRange)
$Script:ExcelWorkBook.Save()
$Script:Excel.Quit()
[gc]::Collect()
[gc]::WaitForPendingFinalizers()
Write-Host "Break"
}
}
PROCESS
{
Set-ScriptVars
Select-File -FileType "xlsx"
Select-File -FileType "txt"
if($Script:TextFile -match "Prescan")
{
Open-Excel -Sheet "Prescan"
}
elseif($Script:TextFile -match "Postscan")
{
Open-Excel -Sheet "Postscan"
}
Get-TextContent
Copy-TextData
}
END
{
}
In this case, utilizing VB macros is not an option.
If such a task is more easily accomplished by leveraging a .NET assembly or dropping in C# code in a #' '# format, I'm all ears!
After spending a great deal of time, I finally came to a workable solution.
For anyone who may come across this through a search engine in the future, I hope the code below helps!
BEGIN
{
Function Set-ScriptVars()
{
Add-Type -AssemblyName System.Windows.Forms
}
Function Select-File($FileType)
{
## Select file via selection dialog
do {
if($FileType -eq "xlsx")
{
Write-Host "`nPlease select the Excel file to import in the dialog"
}
elseif($FileType -eq "txt")
{
Write-Host "`nPlease select the Prescan or Postscan text file to import in the dialog"
}
Start-Sleep -Seconds 1
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{InitialDirectory = [Environment]::GetFolderPath('Desktop')}
[void]$FileBrowser.ShowDialog()
Write-Host "`nFile selected: " -NoNewline
Write-Host $FileBrowser.FileNames -ForegroundColor Yellow
$FileName = $FileBrowser.FileName
if ($FileName.EndsWith(".$FileType"))
{
$selectionValid = $True
}
else
{
Write-Host "The file selected is not a .$FileType file."
Write-Host "Restarting file selection loop."
$selectionValid = $False
}
} until ($selectionValid -eq $True)
if($FileType -eq "txt")
{
$Script:TextFile = $FileName
$Script:TextParentPath = (Get-Item $FileName).Directory.FullName
}
elseif($FileType -eq "xlsx")
{
$Script:ExcelFile = $FileName
$Script:ExcelParentPath = (Get-Item $FileName).Directory.FullName
}
}
Function Open-Excel($Sheet)
{
$ExcelPath = $Script:ExcelFile
$Script:Excel = New-Object -ComObject Excel.Application
$Script:Excel.Visible = $False
$Script:Excel.UserControl = $False
$Script:Excel.Interactive = $True
$Script:Excel.DisplayAlerts = $False
$Script:ExcelWorkBook = $Script:Excel.Workbooks.Open($ExcelPath)
$Script:ExcelWorkSheet = $Script:Excel.WorkSheets.item($Sheet)
$Script:ExcelWorkSheet.Activate()
}
Function Get-TextContent()
{
$Script:TextContent = Get-Content $Script:TextFile
}
function Release-Ref ($ref) {
([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
[System.__ComObject]$ref) -gt 0) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
Function Copy-TextData()
{
# create a CSV from the scan data
$Script:TextContent = Get-Content $Script:TextFile
$data = #()
$row = New-Object PSObject
foreach($line in $Script:TextContent)
{
if($line -eq "CSV was validated without errors." -or $line -eq "")
{
Out-Null
}
else
{
$i = 0
$values = $line -split ","
$result = [PSCustomObject]#{Server=$values[0];`
Role=$values[1];`
Object=$values[2];`
Type=$values[3];`
Path=$values[4]
}
[Array]$results = $results + $result
}
}
$csvName = "scanData_" + "$(#(000..999) | Get-Random)"
$results | Export-CSV -Path "$ENV:USERPROFILE\Desktop\$csvName.csv" -NoTypeInformation
$csvPath = $(Get-Item $ENV:USERPROFILE\Desktop\$csvName.csv).VersionInfo.FileName
# Remove header generated by hashtable
# and skip the next two lines
$tempContent = Get-Content $csvPath
$replacementContent = $tempContent | Select -Skip 3
Set-Content $csvPath -Value $replacementContent
# create temporary workbook and save as xlsx
$tempXL = New-Object -ComObject Excel.Application
$tempXL.Visible = $False
$tempXL.UserControl = $False
$tempXL.Interactive = $True
$tempXL.DisplayAlerts = $False
$tempWB = $tempXL.WorkBooks.Open("$csvPath")
$tempWS = $tempWB.WorkSheets
$convertedName = $csvPath.Replace(".csv",".xlsx")
$tempWB.SaveAs($convertedName,1)
$tempWB.Saved = $True
$tempRange = $tempWB.Worksheets.Item(1).UsedRange
$tempRange.Copy()
if($Script:logSelection -eq "Prescan")
{
$permRange = $Script:ExcelWorkBook.Worksheets.Item(2)
}
else
{
$permRange = $Script:ExcelWorkBook.Worksheets.Item(3)
}
$subRange = $permRange.Range("A2","E2")
$permRange.Paste($subRange)
$permRange.Columns.AutoFit()
$Script:ExcelWorkBook.Save()
$Script:ExcelWorkBook.Saved = $True
$Script:Excel.Quit()
$tempWB.Save()
$tempWB.Saved = $True
$tempXL.Quit()
Release-Ref($Script:ExcelWorkSheet)
Release-Ref($tempWS)
Release-Ref($Script:ExcelWorkBook)
Release-Ref($tempWB)
Release-Ref($Script:Excel)
Release-Ref($tempXL)
Remove-Item $csvPath -Force
Get-Item $convertedName | Remove-Item -Force
}
Function Prompt-ReRun
{
do
{
$openChoice = Read-Host "`nRun again? (y/n)"
$openChoice = $openChoice.ToLower()
} until($openChoice -eq "y" -or $openChoice -eq "n")
if($openChoice -ne "y" -and $openChoice -ne "n")
{
Write-Host "Invalid entry"
}
elseif($openChoice -eq "y")
{
Run-Selection
}
else
{
Out-Null
}
}
Function Run-Selection
{
Select-File -FileType "xlsx"
Select-File -FileType "txt"
if($Script:TextFile -match "Prescan")
{
Open-Excel -Sheet "Prescan"
$Script:logSelection = "Prescan"
}
elseif($Script:TextFile -match "Postscan")
{
Open-Excel -Sheet "Postscan"
$Script:logSelection = "Postscan"
}
Get-TextContent
Copy-TextData
Prompt-ReRun
}
}
PROCESS
{
Set-ScriptVars
Run-Selection
}
END
{
}
I would like to connect DotCMIS.dll to my SharePoint but does not work correct.
I open the script in the SharePoint 2013 Management Shell.
I use my user permissions (This is not a Farm user)
Probably here's the problem with giving the correct link. org.apache.chemistry.dotcmis.binding.atompub.url=?
Have you got any idea where link in sharepoint have to go?
Website of example:
http://chemistry.apache.org/dotnet/powershell-example.html
Error
You cannot call a method on a null-valued expression.
At line:6 char:7
+ $b = $contentStream.Stream.Read($buffer, 0, 4096)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Important part of my Script
$sp["org.apache.chemistry.dotcmis.binding.atompub.url"] = "http://localhost/_layouts/15/start.aspx#/SitePages/WebSite.aspx"
$sp["org.apache.chemistry.dotcmis.user"] = "mylogin"
$sp["org.apache.chemistry.dotcmis.password"] = "mypassword"
All Script
# load DotCMIS DLL
[Reflection.Assembly]::LoadFile("C:\dotCmisServer\DotCMIS.dll")
# -----------------------------------------------------------------
# helper functions
function New-GenericDictionary([type] $keyType, [type] $valueType) {
$base = [System.Collections.Generic.Dictionary``2]
$ct = $base.MakeGenericType(($keyType, $valueType))
New-Object $ct
}
function New-ContentStream([string] $file, [string] $mimetype) {
$fileinfo = ([System.IO.FileInfo]$file)
$contentStream = New-Object "DotCMIS.Data.Impl.ContentStream"
$contentStream.Filename = $fileinfo.Name
$contentStream.Length = $fileinfo.Length
$contentStream.MimeType = $mimetype
$contentStream.Stream = $fileinfo.OpenRead()
$contentStream
}
function Download-ContentStream([DotCMIS.Client.IDocument] $document, [string] $file) {
$contentStream = $document.GetContentStream()
$fileStream = [System.IO.File]::OpenWrite($file)
$buffer = New-Object byte[] 4096
do {
$b = $contentStream.Stream.Read($buffer, 0, 4096)
$fileStream.Write($buffer, 0, $b)
}
while ($b -ne 0)
$fileStream.Close()
$contentStream.Stream.Close()
}
# -----------------------------------------------------------------
# create session
$sp = New-GenericDictionary string string
$sp["org.apache.chemistry.dotcmis.binding.spi.type"] = "atompub"
$sp["org.apache.chemistry.dotcmis.binding.atompub.url"] = "http://localhost/_layouts/15/start.aspx#/SitePages/WebSite.aspx"
$sp["org.apache.chemistry.dotcmis.user"] = "mylogin"
$sp["org.apache.chemistry.dotcmis.password"] = "mypassword"
$factory = [DotCMIS.Client.Impl.SessionFactory]::NewInstance()
$session = $factory.GetRepositories($sp)[0].CreateSession()
# print the repository infos
$session.RepositoryInfo.Id
$session.RepositoryInfo.Name
$session.RepositoryInfo.Vendor
$session.RepositoryInfo.ProductName
$session.RepositoryInfo.ProductVersion
# get root folder
$root = $session.GetRootFolder()
# print root folder children
$children = $root.GetChildren()
foreach ($object in $children) {
$object.Name + " (" + $object.ObjectType.Id + ")"
}
# run a quick query
$queryresult = $session.Query("SELECT * FROM cmis:document", $false)
foreach ($object in $queryresult) {
foreach ($item in $object.Properties) {
$item.QueryName + ": " + $item.FirstValue
}
"----------------------------------"
}
# create a folder
$folderProperties = New-GenericDictionary string object
$folderProperties["cmis:name"] = "myNewFolder"
$folderProperties["cmis:objectTypeId"] = "cmis:folder"
$folder = $root.CreateFolder($folderProperties)
# create a document
$documentProperties = New-GenericDictionary string object
$documentProperties["cmis:name"] = "myNewDocument"
$documentProperties["cmis:objectTypeId"] = "cmis:document"
$source = $home + "\source.txt"
$mimetype = "text/plain"
$contentStream = New-ContentStream $source $mimetype
$doc = $folder.CreateDocument($documentProperties, $contentStream, $null)
# download a document
$target = $home + "\target.txt"
Download-ContentStream $doc $target
# clean up
$doc.Delete($true)
$folder.Delete($true)
Unfortunately in SharePoint Foundation 2013 I have to write own C# software.
SharePoint Foundation 2013 IMPORT\EXPORT dbo.allDocs file\files