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
{
}
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 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"
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: Added the whole converted c# to PowerShell with issue
I'm trying to convert MSDN C# code to PowerShell script.
Here's the MSDN link
I almost finished the conversion but I encounter some issues for my last line.
This is the complete error message: Exception calling "CreateDataDrivenSubscription" with "7" argument(s): "There was an error generating the XML document."
Below is the code snippet for the 7th argument in creating data driven subscription.
Here's the PowerShell script:
$Parameters | Add-Member -type NoteProperty -Name $EMPID.ParameterName -Value $EMPID.FieldAlias
$ReportYear = New-Object $ParameterValue
$ReportYear.Name = "ReportYear"
$ReportYear.Value = "2017"
$Parameters | Add-Member -type NoteProperty -Name $ReportYear.Name -Value $ReportYear.Value
$ReportMonth = New-Object $ParameterValue
$ReportMonth.Name = "ReportMonth"
$ReportMonth.Value = "6"
$Parameters | Add-Member -Type NoteProperty -Name $ReportMonth.Name -Value $ReportMonth.Value
$SubscriptionID = $objWebServerProxy.CreateDataDrivenSubscription($Report,$Settings,$arrDataRetrievalPlan,$Description,$EventType,$MatchData,$Parameters)
Here's the C# code
ParameterValueOrFieldReference[] parameters = new ParameterValueOrFieldReference[3];
ParameterFieldReference empID = new ParameterFieldReference(); // Data-driven.
empID.ParameterName = "EmpID";
empID.FieldAlias = "EmpID";
parameters[0] = empID;
ParameterValue reportYear = new ParameterValue();
reportYear.Name = "ReportYear";
reportYear.Value = "2004";
parameters[1] = reportYear;
ParameterValue reportMonth = new ParameterValue();
reportMonth.Name = "ReportMonth";
reportMonth.Value = "6"; // June
parameters[2] = reportMonth;
try
{
string subscriptionID = rs.CreateDataDrivenSubscription(
report, settings, dataRetrieval, description, eventType, matchData, parameters);
Can you tell me where did I miss on the conversion?
Here's my whole converted script.
$URI = "URI"
$objWebServerProxy = New-WebServiceProxy -Uri $URI -UseDefaultCredential -ErrorAction Stop
$Namespace = $objWebServerProxy.GetType().Namespace
$ExtensionSettigs = ($Namespace + '.ExtensionSettings')
$ParameterValueOrFieldReference = ($Namespace + '.ParameterValueOrFieldReference')
$ParameterFieldReference = ($Namespace + '.ParameterFieldReference')
$ParameterValue = ($Namespace + '.ParameterValue')
$Datasource = ($Namespace + '.DataSource')
$DataSourceDefinition = ($Namespace + '.DataSourceDefinition')
$Field = ($Namespace + '.Field')
$CredentialRetrievalEnum = ($Namespace + '.CredentialRetrievalEnum')
$DataSetDefinition = ($Namespace + '.DataSetDefinition')
$QueryDefinition = ($Namespace + '.QueryDefinition')
$DataSetDefinition = ($Namespace +'.DataSetDefinition')
$DataRetrievalPlan = ($Namespace+'.DataRetrievalPlan')
$ScheduleReference = ($Namespace+'.ScheduleReference')
$NameSharedSchedule="Mike_Test";
$NeverExpireSchedule= $objWebServerProxy.ListSchedules([System.Management.Automation.Language.NullString]::Value) | where {$_.Name -eq "$NameSharedSchedule"}
$NeverExpireScheduleID = $NeverExpireSchedule.scheduleid;
$NeverExpireDescription = $NeverExpireSchedule.Description;
$NeverExpireDefinition = $NeverExpireSchedule.Definition;
#Write-Host "Found Shared Schedule: '$NameSharedSchedule' with id $NeverExpireScheduleID and definition $NeverExpireDescription";
$NeverExpireScheduleRef =New-Object $ScheduleReference
$NeverExpireScheduleRef.ScheduleID=$NeverExpireScheduleID;
#$Report = "/ForMigration/Subscription_Test/SSRSRationalization_ExecutionLog_LastEightDays"
$Report = "/Gayatree/GTest/ExecutionLog_LastEightDays"
$Description = "My new Data Driven Subscription"
$Settings = New-Object $ExtensionSettigs
$Settings.Extension = "Report Server Email";
$ExtensionParams = New-Object $ParameterValueOrFieldReference
#$ExtensionParams.ParameterValueOrFieldReference ='8'
$To = New-Object $ParameterFieldReference
$To.ParameterName = "TO"
$To.FieldAlias = "Email"
$ExtensionParams | Add-Member -type NoteProperty -name $To.ParameterName -Value $To.FieldAlias
$ReplyTo = New-Object $ParameterValue
$ReplyTo.Name = "ReplyTo"
$ReplyTo.Value = "Email"
$ExtensionParams | Add-Member -type NoteProperty -name $ReplyTo.Name -Value $ReplyTo.Value
$IncludeReport = New-Object $ParameterValue
$IncludeReport.Name = "IncludeReport"
$IncludeReport.Value = $false
$ExtensionParams | Add-Member -type NoteProperty -name $IncludeReport.Name -Value $IncludeReport.Value
$RenderFormat = new-object $ParameterValue
$RenderFormat.Name = "ReportFormat";
$RenderFormat.Value = "HTML4.0"
$ExtensionParams | Add-Member -type NoteProperty -name $RenderFormat.Name -Value $RenderFormat.Value
$Priority = New-Object $ParameterValue
$Priority.Name = "Priority"
$Priority.Value = "Normal"
$ExtensionParams | Add-Member -type NoteProperty -name $Priority.Name -Value $Priority.Value
$Subject = New-Object $ParameterValue
$Subject.Name = "Subject"
$Subject.Value = "Your sales report"
$ExtensionParams | Add-Member -type NoteProperty -name $Subject.Name -Value $Subject.Value
$Comment = New-Object $ParameterValue
$Comment.Name = "Comment"
$Comment.Value = "Here is the link to your report."
$ExtensionParams | Add-Member -type NoteProperty -name $Comment.Name -Value $Comment.Value
$IncludeLink = New-Object $ParameterValue
$IncludeLink.Name = "IncludeLink";
$IncludeLink.Value = $true
$ExtensionParams | Add-Member -Type NoteProperty -name $IncludeLink.Name -Value $IncludeLink.Value
$Settings.ParameterValues = $ExtensionParams
$DSName = New-Object $Datasource
$DSName.Name = "Mike_Test"
<#
$DSDefinition = New-Object $DataSourceDefinition
$CredentialRetrieval = New-Object $CredentialRetrievalEnum
$CredentialRetrieval.value__ = 1
$DSDefinition.ConnectString = "Data source = server;Initial Catalog = ReportServer"
$DSDefinition.CredentialRetrieval = $CredentialRetrieval
$DSDefinition.Enabled = $true
$DSDefinition.EnabledSpecified = $true
$DSDefinition.Extension = "SQL"
$DSDefinition.ImpersonateUserSpecified = $false
$DSDefinition.UserName = "Username"
$DSDefinition.Password = "Password"
#>
$DS = $objWebServerProxy.ListChildren('/',$false)|Where-Object {$_.TypeName -eq "DataSource"}
foreach($DSS in $DS){
$anotherPass = $DSS.path
$another = $objWebServerProxy.GetDataSourceContents("$anotherPass")
$another.Password = "TestPass"
}
$another
$DSName.Item = $another
$FieldList = New-Object $Field
$FieldList.Name = "EmailAddress"
$FieldList.Alias = "EmailAddress"
$FieldList | Add-Member -Type NoteProperty -name $FieldList.Name -Value $FieldList.Alias
$FieldList.Name = "EmpID"
$FieldList.Alias = "EmpID"
$FieldList | Add-Member -Type NoteProperty -name $FieldList.Name -Value $FieldList.Alias
$DataSetDef = New-Object $DataSetDefinition
$DataSetDef.AccentSensitivitySpecified = $false
$DataSetDef.CaseSensitivitySpecified = $false
$DataSetDef.KanatypeSensitivitySpecified = $false
$DataSetDef.WidthSensitivitySpecified = $false
$DataSetDef.Fields = $FieldList
$arrQueryDefinition = New-Object $QueryDefinition
$arrQueryDefinition.CommandText = "Select getdate()"
$arrQueryDefinition.CommandType = "Text"
$arrQueryDefinition.Timeout = '45'
$arrQueryDefinition.TimeoutSpecified = $true
$DataSetDef.Query = $arrQueryDefinition
$Results = New-Object $DataSetDefinition
$Bool = $true
$Name = "Parameter"
$DSDefinition
$DataSetDef
$DSName
$Results = $objWebServerProxy.PrepareQuery($DSName,$DataSetDef,[ref]$Bool,[ref]$Name)
$arrDataRetrievalPlan = New-Object $DataRetrievalPlan
$arrDataRetrievalPlan.DataSet = $Results
$arrDataRetrievalPlan.Item = $another
$EventType = "TimedSubscription";
$MatchData = $NeverExpireScheduleID
$Parameters = New-Object $ParameterValueOrFieldReference
#
$EMPID = New-Object $ParameterFieldReference
$EMPID.ParameterName = "EmpID"
$EMPID.FieldAlias = "EmpID"
$Parameters | Add-Member -type NoteProperty -Name $EMPID.ParameterName -Value $EMPID.FieldAlias
$ReportYear = New-Object $ParameterValue
$ReportYear.Name = "ReportYear"
$ReportYear.Value = "2017"
$Parameters | Add-Member -type NoteProperty -Name $ReportYear.Name -Value $ReportYear.Value
$ReportMonth = New-Object $ParameterValue
$ReportMonth.Name = "ReportMonth"
$ReportMonth.Value = "6"
$Parameters | Add-Member -Type NoteProperty -Name $ReportMonth.Name -Value $ReportMonth.Value
$SubscriptionID = $objWebServerProxy.CreateDataDrivenSubscription($Report,$Settings,$arrDataRetrievalPlan,$Description,$EventType,$MatchData,$Parameters)
I'm not sure if the way you're creating the ParameterValue instances works - I can't tell for sure since the $ParameterValue declaration is missing, but chances are this causes the problem.
You might want to try something more along the lines of this:
$reportServerUri = "http://localhost/reportserver/ReportService2010.asmx?wsdl"
$rs = New-WebServiceProxy -Uri $reportServerUri -UseDefaultCredential -Namespace "SSRS"
# Note the difference, here we use the type generated when creating the webservice proxy:
$ReportYear = New-Object SSRS.ParameterValue
$ReportYear.Name = "ReportYear"
$ReportYear.Value = "2017"
See my blog post here for a quick tutorial.
Edit
To pinpoint which argument of CreateDataDrivenSubscription the error is, try substituting one or more arguments with $null - sure it might be invalid according to the method's documentation, but the null checks only occur once the call has been successfully sent to the server and deserialized.
In other words, if substituting the $Parameters argument with $null does not throw the "error generating XML document", then the error is in the $Parameters argument:
$SubscriptionID = $objWebServerProxy.CreateDataDrivenSubscription($Report,$Settings,
$arrDataRetrievalPlan,$Description,$EventType,$MatchData,$null)
I am trying to run a powershell script in c#
here is the first test script
param(
[string] $computer,
[string] $password
)
out-file -filepath C:\File\parameter.txt -inputobject $computer -encoding ASCII -width 50 -Append
out-file -filepath C:\File\params.txt -inputobject $password -encoding ASCII -width 50 -Append
out-file -filepath C:\File\Sys32.txt -inputobject $password -encoding ASCII -width 50 -Append
and here is my C# supposed to run the powershellscript
private void testRunningPowershell()
{
string mypass = gettingPass();
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
runspace.SessionStateProxy.Path.SetLocation("C:\\Users\\robert\\Desktop\\Titanium\\");
RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
//runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
// create a pipeline and feed it the script text (AddScript method) or use the filePath (Add method)
using (Pipeline pipeline = runspace.CreatePipeline())
{
Command command = new Command(#"C:\Users\robert\Desktop\Titanium\Titanium2.ps1");
dictionaryParams.Remove("FriendlyName");
foreach (var item in dictionaryParams)
{
if (item.Key == (string)comboBoxScreen.SelectedItem)
{
CommandParameter testParam = new CommandParameter(null, item.Value);
CommandParameter testParam2 = new CommandParameter(null, mypass);
command.Parameters.Add(null, testParam);
command.Parameters.Add(null, testParam2);
}
}
pipeline.Commands.Add(command);
var results = pipeline.Invoke();
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in results)
{
Hashtable ht = p.ImmediateBaseObject as Hashtable;
ri.ReturnText = (string)ht["ComputerName"];
ri.ReturnText = (string)ht["password"];
}
runspace.Close();
}
}
}
my purpose is to test if the cmdlet is run with the right parameters
I've got a windows form app that allow the user to choose the parameter
I would like to get my parameter value written in Text File (.txt)
instead I am getting this
System.Management.Automation.Runspaces.CommandParameter
instead of the parameter's value choosen