My script runs in Powershell V2.0 ISE but does not run in Powershell script. Why is this? I understand the variables cannot be null here, however I read these from the XAML and the button clicks do work. I get the following error:
You cannot call a method on a null-valued expression,
At C:\Program Files (x86)\Novertz\Main Script\Novertz.ps1 char:7
+ $FEL_CP6K01_button.add.click <<<< <<
+Category Info :InvalidOperation
I read the XAML with the following:
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$XamlPath
)
[xml]$Global:xmlWPF = Get-Content -Path $XamlPath
#Add WPF and Windows Forms assemblies
try{
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
} catch {
Throw "Failed to load Windows Presentation Framework assemblies."
}
#Create the XAML reader using a new XML node reader
$Global:xamGUI = [Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))
#Create hooks to each named object in the XAML
$xmlWPF.SelectNodes("//*[#Name]") | %{
Set-Variable -Name ($_.Name) -Value $xamGUI.FindName($_.Name) -Scope Global
}
And the powershell script:
#Required to load the XAML form and create the PowerShell Variables
cd "C:\Users\Leeds TX 12\Desktop\Novertz\GUI"
./LoadDialog.ps1 -XamlPath 'C:\Users\Leeds TX 12\Desktop\Novertz\GUI\myform.xaml'
$FEL_CP6K01_button.add_Click({#powershell script#})
$xamGUI.ShowDialog() | out-null
XAML:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="No-Vertz" Height="1080" Width="1920">
<Grid Margin="0,0,-233,-101"> <Grid.Effect> <DropShadowEffect/> </Grid.Effect>
<Button Name="FEL_CP6K01_button" Content="FEL_CP6K_CH01" HorizontalAlignment="Left" Margin="23,69,0,0" VerticalAlignment="Top" Width="99" Height="59"/>
Run powershell in single threaded apartment mode -STA
Related
I configured winpe with powershell anable plus to WPF script and the script have a image file ".jpg" but that image dont load when run winpe.
Message eror:
Exception setting "Source": "Cannot convert value "x:\scripts\e9.jpg" to type "System.windows.Media.ImageSource".
Error: "Object reference not set to an instance of an Objet."
At x:\script\Minio.ps1:485 char:1
+ $image.Source - $Source
Script:
$Source = "x:\scripts\e9.jpg"
$Image = New-Object System.Windows.Controls.Image
$Image.Source = $Source
$Image.Height = [System.Drawing.Image]::FromFile($Source).Height / 1
$Image.Width = [System.Drawing.Image]::FromFile($Source).Width / 1
$TextBlock = New-Object System.Windows.Controls.TextBlock
$TextBlock.Text = "CLIQUE OK para REINICIAR"
$TextBlock.FontSize = "16"
$TextBlock.HorizontalAlignment = "Center"
$StackPanel = New-Object System.Windows.Controls.StackPanel
$StackPanel.AddChild($Image)
$StackPanel.AddChild($TextBlock)
New-WPFMessageBox -Content $StackPanel -Title "Atenção!" -TitleBackground LightSeaGreen -TitleTextForeground Black -ContentBackground LightSeaGreen
When I execute this script inside of Powershell ISE it completes. When I run this in WinPE it fails.
Before load this script, run this. Another script without image.jpg run perfect.
https://gist.github.com/SMSAgentSoftware/0c0eee98a673b6ac34f5215ea6841beb
from project: SMSAgentSoftware/New-WPFMessageBox
Any ideas on what I am doing wrong?
I have a Powershell script that displays a System.Windows.Forms to trim audio files. This form loads an audio waveform that was created by the script.
When I close the form, I would like to remove this waveform file.
I have tried adding this but it doesn't work.
$form.Controls.Remove($pictureBox)
$form.Refresh()
Remove-Item -Path $FilepathForWaveform -Force
This also doesn't work:
$form.Dispose()
Remove-Item -Path $FilepathForWaveform -Force
I have seen this answer, but when I implement it, the script close without removing the image.
I use Powershell 5.1
My whole script is here and this is the relevant parts:
ffmpeg -i $file_name_complete -filter_complex "showwavespic=s=640x120" -frames:v 1 $DirectoryPath\"output.png" -y
$FilepathForWaveform = dir -LiteralPath $DirectoryPath\"output.png"
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object System.Windows.Forms.Form
$img = [System.Drawing.Image]::Fromfile($FilepathForWaveform)
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Width = $img.Size.Width
$pictureBox.Height = $img.Size.Height
$pictureBox.Image = $img
$pictureBox.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom
$pictureBox.Location = "15, 200"
$form.controls.add($pictureBox)
$form.ShowDialog()
Now, I am able to remove the image when the form is closed but the image is not displayed:
$FilepathForWaveform = dir -LiteralPath $DirectoryPath\"output.png"
$img = Image.FromStream(new MemoryStream(File.ReadAllBytes("[$FilepathForWaveform]")))
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Image = $img
$form.controls.add($pictureBox)
$form.Add_Closing({
$form.Controls.Remove($pictureBox)
$pictureBox.Dispose()
$form.Refresh()
Remove-Item -Path $FilepathForWaveform -Force
})
$form.ShowDialog() | Out-Null
$form.Dispose()
I have also tried this based on this link:
$img=[System.Drawing.Image]::FromStream([System.IO.MemoryStream]$FilepathForWaveform)
I have a program with a main window (powershell wpf/xaml). That program does a check for files and opens a second window, if something is missing it must have a link to the folder, i use .Add_PreviewMouseDown({ }) for that. That works, but if i run a second check, window 2 gets the same "link to folder" as window 3. How can i get it to work, that links of window 2 dont get updatet?
i already tried to get dynamic Label Names and PreviewMouseDown's but that isnt enough.
$Script:WindowNumber += 1
$WindowName = "Win$WindowNumber"
$CEMessage = '<Label Name="CEFout' + $WindowNumber + '" HorizontalAlignment="Left" Margin="30,288,0,0" VerticalAlignment="Top" Width="142" FontSize="14" ToolTip="Fileserver Folder" >
<Hyperlink NavigateUri="Bureaublad\Machine Folder">⨯ CE:</Hyperlink>
</Label>'
New-Variable -Name "BijlagenWPF$WindowNumber" -Value ($BijlagenWPF = #"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Bijlagen" Height="420" Width="250" Icon="$Icon" ResizeMode="NoResize" ShowInTaskbar="True">
<Grid HorizontalAlignment="Center" Margin="0,0,0,0" Width="240">
$CEMessage
</Grid>
</Window>
"# -as [XML])
$NR2=(New-Object System.Xml.XmlNodeReader (Get-Variable | Where-Object Name -eq "BijlagenWPF$WindowNumber").Value)
New-Variable -Name $WindowName -Value ([Windows.Markup.XamlReader]::Load( $NR2 ))
$BijlagenWPF.SelectNodes("//*[#*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach-Object {
New-Variable -Name $_.Name -Value (Get-Variable | Where-Object Name -eq $WindowName).Value.FindName($_.Name) -Force
}
(Get-Variable | Where-Object Name -eq "CEFout$WindowNumber").Value.Add_PreviewMouseDown({[system.Diagnostics.Process]::start("$Desktop\$Machine\Fileserver\manual\bijlagen")})
(Get-Variable | Where-Object Name -eq $WindowName).Value.Show()
This is a screenshot of the 2 windows with opened link. Now the link in the first window (2532-163) is the same as the second window (2532-164). But has to be 2532-163 folder
I want to get a copy of all .rdl files in one server.
I can do the download manually one report at the time, but this is time consuming especially that this server has around 1500 reports.
Is there any way or any tool that allows me to download all the .rdl files and take a copy of them?
There is a complete & simpler way to do this using PowerShell.
This code will export ALL report content in the exact same structure as the Report server. Take a look at the Github wiki for other options & commands
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = 'http://ReportServerURL/ReportServer/ReportService2010.asmx?wsdl'
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\SSRS_Out' -Recurse
I've created this powershell script to copy them into a ZIP. You have to provide the SQL server database details.
Add-Type -AssemblyName "System.IO.Compression.Filesystem"
$dataSource = "SQLSERVER"
$user = "sa"
$pass = "sqlpassword"
$database = "ReportServer"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pass;Database=$database;Integrated Security=False;"
$tempfolder = "$env:TEMP\Reports"
$zipfile = $PSScriptRoot + '\reports.zip'
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$allreports = $connection.CreateCommand()
$allreports.CommandText = "SELECT ItemID, Path, CASE WHEN Type = 2 THEN '.rdl' ELSE '.rds' END AS Ext FROM Catalog WHERE Type IN(2,5)"
$result = $allreports.ExecuteReader()
$reportable = new-object "System.Data.DataTable"
$reportable.Load($result)
[int]$objects = $reportable.Rows.Count
foreach ($report in $reportable) {
$cmd = $connection.CreateCommand()
$cmd.CommandText = "SELECT CAST(CAST(Content AS VARBINARY(MAX)) AS XML) FROM Catalog WHERE ItemID = '" + $report[0] + "'"
$xmldata = [string]$cmd.ExecuteScalar()
$filename = $tempfolder + $report["Path"].Replace('/', '\') + $report["Ext"]
New-Item $filename -Force | Out-Null
Set-Content -Path ($filename) -Value $xmldata -Force
Write-Host "$($objects.ToString()).$($report["Path"])"
$objects -= 1
}
Write-Host "Compressing to zip file..."
if (Test-Path $zipfile) {
Remove-Item $zipfile
}
[IO.Compression.Zipfile]::CreateFromDirectory($tempfolder, $zipfile)
Write-Host "Removing temporarly data"
Remove-Item -LiteralPath $tempfolder -Force -Recurse
Invoke-Item $zipfile
If you just need this for backup purposes or something similar, this might be useful: Where does a published RDL file sit?
The relevant query from that thread is:
select convert(varchar(max), convert(varbinary(max), content))
from catalog
where content is not null
The original answer was using 2005, and I've used it on 2016, so I imagine it should work for 2008 and 2012.
When I had to use this, I added in the Path to the query as well, so that I knew which report was which.
CAVEAT: prior to SSMS v18, Results to Grid is limited to 64KB per tuple and Results to Text are limited to 8,192 characters per tuple. If your report definition is larger than these limits you will not be able to get the entire definition.
In SSMS v18, those limits have been increased to 2MB per tuple for both Reports to Grid as well as Results to Text.
This is based on SQL2016/SSRS2016 but I think it should work for 2012.
SELECT 'http://mySQLServerName/reports/api/v1.0/catalogitems(' + cast(itemid as varchar(256))+ ')/Content/$value' AS url
FROM ReportServer.dbo.Catalog
This will give you a list of URL's, one for each report.
If the above did not work in SSRS 2012 then go to the report manager and do as if you were going to download the file from there. Check the URL on the download button and you'll probably see a URL with and item id embedded int it. Just adjust the above code to match that url structure.
What you do with then after this is up to you.
Personally I would use the Chrome extension called 'Tab Save' available in the Chrome store here. You can simply copy and paste all the URL's created above into it and hit the download button...
Found and used this without any issues. Nothing to install, just added my url, and pasted into Powershell.
https://microsoft-bitools.blogspot.com/2018/09/ssrs-snack-download-all-ssrs-reports.html
In case the link breaks, here's the code from the link:
###################################################################################
# Download Reports and DataSources from a SSRS server and create the same folder
# structure in the local download folder.
###################################################################################
# Parameters
###################################################################################
$downloadFolder = "c:\temp\ssrs\"
$ssrsServer = "http://myssrs.westeurope.cloudapp.azure.com"
###################################################################################
# If you can't use integrated security
#$secpasswd = ConvertTo-SecureString "MyPassword!" -AsPlainText -Force
#$mycreds = New-Object System.Management.Automation.PSCredential ("MyUser", $secpasswd)
#$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -Credential $mycreds
# SSRS Webserver call
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -UseDefaultCredential
# List everything on the Report Server, recursively, but filter to keep Reports and DataSources
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}
# Loop through reports and data sources
Foreach($ssrsItem in $ssrsItems)
{
# Determine extension for Reports and DataSources
if ($ssrsItem.TypeName -eq "Report")
{
$extension = ".rdl"
}
else
{
$extension = ".rds"
}
# Write path to screen for debug purposes
Write-Host "Downloading $($ssrsItem.Path)$($extension)";
# Create download folder if it doesn't exist (concatenate: "c:\temp\ssrs\" and "/SSRSFolder/")
$downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim()
New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null
# Get SSRS file bytes in a variable
$ssrsFile = New-Object System.Xml.XmlDocument
[byte[]] $ssrsDefinition = $null
$ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)
# Download the actual bytes
[System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(#(,$ssrsDefinition))
$ssrsFile.Load($memoryStream)
$fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name + $extension;
$ssrsFile.Save($fullDataSourceFileName);
}
I'vr tried several permutations of this script and keep getting the "can't create proxy connection" error. Here's the one that "should" work:
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = "http://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl"
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\Users\arobinson\source\Workspaces\EDW\MAIN\SSRS\HQMNBI' -Recurse
This is the error I'm getting:
Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The HTML document does not contain
Web service discovery information.
At C:\Program Files\WindowsPowerShell\Modules\ReportingServicesTools\0.0.6.6\Functions\Utilities\New-RsWebServiceProxy.ps1:136 char:9
throw (New-Object System.Exception("Failed to establish proxy ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : OperationStopped: (:) [], Exception
FullyQualifiedErrorId : Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The
HTML document does not contain Web service discovery information.
I've tried the URI with htttp:// and without, I've tried including the port number. etc. Still can't get this to actually work. We have two other SSRS instances that I was able to run this against no problem.
From this question: SQL Reporting Services - COPY reports to another folder
I found this tool can both download and upload reports. Plus it lists out folders and subfolders.
http://code.google.com/p/reportsync/
So I've managed to deploy our DACPAC schema via Octopus. I'm using a Deploy.ps1 script interacting with .Net objects just like the article describes.
I'd like to make the deployment process more transparent by including the "standard output" you get from sqlcmd in our Octopus logs. I'm looking for the the generated schema modification messages as well as any custom migration migration messages our developers have put into the pre/post scripts.
The only workaround I can think of is to first generate the script with the DACPAC services and then run it with sqlcmd.exe. Any ideas?
Found the solution, posting in case someone else runs across this. You simply need to subscribe to the your DacService's Message event.
C# sample:
var services = new Microsoft.SqlServer.Dac.DacServices("data source=machinename;Database=ComicBookGuy;Trusted_connection=true");
var package = Microsoft.SqlServer.Dac.DacPackage.Load(#"C:\Database.dacpac");
var options = new Microsoft.SqlServer.Dac.DacDeployOptions();
options.DropObjectsNotInSource = true;
options.SqlCommandVariableValues.Add("LoginName", "SomeFakeLogin");
options.SqlCommandVariableValues.Add("LoginPassword", "foobar!");
services.Message += (object sender, Microsoft.SqlServer.Dac.DacMessageEventArgs eventArgs) => Console.WriteLine(eventArgs.Message.Message);
services.Deploy(package, "ComicBookGuy", true, options);
Powershell sample (executed by the Octopus Tentacle):
# This script is run by Octopus on the tentacle
$localDirectory = (Get-Location).Path
$tagetServer = $OctopusParameters["SQL.TargetServer"]
$databaseName = "ComicBookGuy"
Add-Type -path "$localDirectory\lib\Microsoft.SqlServer.Dac.dll"
$dacServices = New-Object Microsoft.SqlServer.Dac.DacServices ("data source=" + $tagetServer + ";Database=" + $databaseName + "; Trusted_connection=true")
$dacpacFile = "$localDirectory\Content\Unity.Quotes.Database.dacpac"
$dacPackage = [Microsoft.SqlServer.Dac.DacPackage]::Load($dacpacFile)
$options = New-Object Microsoft.SqlServer.Dac.DacDeployOptions
$options.SqlCommandVariableValues.Add("LoginName", $OctopusParameters["SQL.LoginName"])
$options.SqlCommandVariableValues.Add("LoginPassword", $OctopusParameters["SQL.LoginPassword"])
$options.DropObjectsNotInSource = $true
Register-ObjectEvent -InputObject $dacServices -EventName "Message" -Action { Write-Host $EventArgs.Message.Message } | out-null
$dacServices.Deploy($dacPackage, $databaseName, $true, $options)
In the powershell version I couldn't get the handy "Add_EventName" style of event notification working so I had to use the clunky cmdlet. Meh.
Use sqlpackage instead of sqlcmd to deploy dacpac.
Get Latest version here : https://msdn.microsoft.com/en-us/mt186501
$sqlpackage = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\120\sqlpackage.exe"
It will automatically output errors on the console. We use TFS build definition and call powershell and it is able to display errors that happened during a deploy.
Usage:
& $sqlpackage /Action:Publish /tsn:$dbServer /tdn:$database /sf:$mydacpac/pr:$dbProfile /variables:myVariable=1
This variation captures output but also allows you to capture and react to deploy failures by catching the exception
function Load-DacPacAssembly()
{
$assemblyName = "Microsoft.SqlServer.Dac.dll"
$packageFolder = <some custom code to find our package folder>
$dacPacAssembly = "$packageFolder\lib\net46\$assemblyName"
Write-Host "Loading assembly $assemblyName"
Add-Type -Path "$dacPacAssembly"
}
function Publish-Dacpac($dacpac, $publishProfile){
Load-DacPacAssembly
Write-Host "Loading profile $publishProfile..."
$dacProfile = [Microsoft.SqlServer.Dac.DacProfile]::Load($publishProfile)
$dacService = New-Object Microsoft.SqlServer.dac.dacservices ($dacProfile.TargetConnectionString)
Write-Host "Loading dacpac $dacpac"
$dacPackage = [Microsoft.SqlServer.Dac.DacPackage]::Load($dacpac)
$event = Register-ObjectEvent -InputObject $dacService -EventName "Message" -Action {
$message = $EventArgs.Message
$colour = "DarkGray"
if ($message -contains "Error SQL")
{
$colour = "Red"
}
Write-Host $message -ForegroundColor $colour
}
Write-Host "Publishing...."
try {
$dacService.deploy($dacPackage, $dacProfile.TargetDatabaseName, $true, $dacProfile.DeployOptions)
}
catch [Microsoft.SqlServer.Dac.DacServicesException]
{
$message = $_.Exception.Message
Write-Host "SQL Publish failed - $message" -ForegroundColor Red # Customise here for your build system to detect the error
exit;
}
finally
{
Unregister-Event -SourceIdentifier $event.Name
}
}