Remove item from Programs and Features list in Windows 7

If the uninstallation of an program fails, the item will not be removed from the “Programs and Features” list on the Control Panel in Windows 7.

To remove the item, remove the item from the registry key:

Windows 7 x64

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

 

Windows 7 x86

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

 

Note

Removing the key will only remove the item form the “Programs and Features” list, if you want to re-install the program you should also find the productcode and the corresponding upgrade code, then remove the entry from:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes

How to deploy a report (*.rdl) file to SQL Server Reporting Services using PowerShell

If you want to deploy a report (*.rdl) file to SQL Server Reporting Services in PowerShell, use the following script:

 

PowerShell script

"Set execution policy to [Unrestricted]"
Set-ExecutionPolicy Unrestricted

"Load assembly"
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Ada.Cdf.dll")

"Create report"
$report = New-Object Ada.Cdf.Deployment.SSRS.Report
$report.SSRSWebServiceUrl = "http://localhost/ReportServer/ReportService2005.asmx"
$report.SSRSFolder = "ADA Sales Reports"
$report.FileSystemPath = "C:\Reports\AanvragenStats.rdl"
$report.Create()

 

C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ada.Cdf.ReportService2005;
namespace Ada.Cdf.Deployment.SSRS
{
public class Report
{
public string FileSystemPath { get; set; }
public string SSRSWebServiceUrl { get; set; }
public string _ssrsFolder = string.Empty;
public string SSRSFolder 
{
get
{
// Use "/" as default value
string firstCharacter = "/";
if (string.IsNullOrEmpty(_ssrsFolder))
{
_ssrsFolder = firstCharacter;
}
// Report folder should start with one "/"
_ssrsFolder = firstCharacter + _ssrsFolder.TrimStart(firstCharacter.ToCharArray());
return _ssrsFolder;
}
set
{
_ssrsFolder = value;
}
}
/// <summary>
/// Create a report
/// </summary>
public void Create()
{
// Validate properties
if (string.IsNullOrEmpty(this.FileSystemPath)) { throw new ArgumentNullException("this.FileSystemPath"); }
if (!File.Exists(this.FileSystemPath)) { throw new ApplicationException(string.Format("The file [{0}] does not exist", this.FileSystemPath)); }
if (string.IsNullOrEmpty(this.SSRSWebServiceUrl)) { throw new ArgumentNullException("this.SSRSWebServiceUrl"); }
if (string.IsNullOrEmpty(this.SSRSFolder)) { throw new ArgumentNullException("this.SSRSFolder"); }
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Determine filename without extension (used as name in SSRS)
FileInfo fileInfo = new FileInfo(this.FileSystemPath);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
// Determine filecontents
byte[] fileContents = File.ReadAllBytes(fileInfo.FullName);
// Publish report
Warning[] warnings = rs.CreateReport(fileNameWithoutExtension, this.SSRSFolder, true, fileContents, null);
// Log warnings
if (warnings != null)
{
foreach (Warning warning in warnings)
{
Global.Logger.Warn(warning);
}
}
}
/// <summary>
/// Delete a report
/// </summary>
public void Delete()
{
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Determine filename without extension (used as name in SSRS)
FileInfo fileInfo = new FileInfo(this.FileSystemPath);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
// Determine full SSRS path
string ssrsPath = string.Format("{0}/{1}", this.SSRSFolder, fileNameWithoutExtension.TrimStart("/".ToCharArray()));
// Delete report
rs.DeleteItem(ssrsPath);
}
}
}

 

Result

image

How to deploy a datasource in SQL Server Reporting Services with PowerShell

If you want to use PowerShell to deploy a datasource in SQL Server Reporting Services use the following script:

 

PowerShell script

"Set execution policy to [Unrestricted]"
Set-ExecutionPolicy Unrestricted

"Load assembly"
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Ada.Cdf.dll")

$datasource = New-Object Ada.Cdf.Deployment.SSRS.DataSource
$datasource.SSRSWebServiceUrl = "http://localhost/ReportServer/ReportService2005.asmx"
$datasource.ImpersonateUser = $false
$datasource.WindowsIntegratedSecurity = $true
$datasource.UserAccountName = "MyDomain\saAsaWeb"
$datasource.UserAccountPassword = "MyPassword"
$datasource.ConnectionString = "Data Source=.;Initial Catalog=AdaSales;Integrated Security=SSPI;"
$datasource.FileSystemPath = "C:\Temp\Reports\AdaSales.rds"
$datasource.SSRSFolder = "ADA Sales Reports"
$datasource.Create()

 

 

C# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ada.Cdf.ReportService2005;
namespace Ada.Cdf.Deployment.SSRS
{
public class DataSource
{
public bool ImpersonateUser { get; set; }
public bool WindowsIntegratedSecurity { get; set; }
public string UserAccountName { get; set; }
public string UserAccountPassword { get; set; }
public string ConnectionString { get; set; }
public string FileSystemPath { get; set; }
public string SSRSWebServiceUrl { get; set; }
public string _ssrsFolder = string.Empty;
public string SSRSFolder
{
get
{
// Use "/" as default value
string firstCharacter = "/";
if (string.IsNullOrEmpty(_ssrsFolder))
{
_ssrsFolder = firstCharacter;
}
// Report folder should start with one "/"
_ssrsFolder = firstCharacter + _ssrsFolder.TrimStart(firstCharacter.ToCharArray());
return _ssrsFolder;
}
set
{
_ssrsFolder = value;
}
}
/// <summary>
/// Create a DataSource
/// </summary>
public void Create()
{
// Validate properties
if (string.IsNullOrEmpty(this.FileSystemPath)) { throw new ArgumentNullException("this.FileSystemPath"); }
if (!File.Exists(this.FileSystemPath)) { throw new ApplicationException(string.Format("The file [{0}] does not exist", this.FileSystemPath)); }
if (string.IsNullOrEmpty(this.SSRSWebServiceUrl)) { throw new ArgumentNullException("this.SSRSWebServiceUrl"); }
if (string.IsNullOrEmpty(this.SSRSFolder)) { throw new ArgumentNullException("this.SSRSFolder"); }
if (string.IsNullOrEmpty(this.UserAccountName)) { throw new ArgumentNullException("this.UserAccountName"); }
if (string.IsNullOrEmpty(this.UserAccountPassword)) { throw new ArgumentNullException("this.UserAccountPassword"); }
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Determine filename without extension (used as name in SSRS)
FileInfo fileInfo = new FileInfo(this.FileSystemPath);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);    
// Create DataSourceDefinition
DataSourceDefinition definition = new DataSourceDefinition();
definition.CredentialRetrieval = CredentialRetrievalEnum.Store;
definition.ConnectString = this.ConnectionString;
definition.UserName = this.UserAccountName;
definition.Password = this.UserAccountPassword;
definition.Enabled = true;
definition.EnabledSpecified = true;
definition.Extension = "SQL";
definition.ImpersonateUser = this.ImpersonateUser;
definition.ImpersonateUserSpecified = true;
// Use the default prompt string
definition.Prompt = null;
definition.WindowsCredentials = this.WindowsIntegratedSecurity;
// Create datasource
rs.CreateDataSource(fileNameWithoutExtension, this.SSRSFolder, true, definition, null);
}
/// <summary>
/// Delete a DataSource
/// </summary>
public void Delete()
{
// Validate properties
if (string.IsNullOrEmpty(this.FileSystemPath)) { throw new ArgumentNullException("this.FileSystemPath"); }
if (string.IsNullOrEmpty(this.SSRSWebServiceUrl)) { throw new ArgumentNullException("this.SSRSWebServiceUrl"); }
if (string.IsNullOrEmpty(this.SSRSFolder)) { throw new ArgumentNullException("this.SSRSFolder"); }
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Determine filename without extension (used as name in SSRS)
FileInfo fileInfo = new FileInfo(this.FileSystemPath);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
// Determine full SSRS path
string ssrsPath = string.Format("{0}/{1}", this.SSRSFolder, fileNameWithoutExtension.TrimStart("/".ToCharArray()));
// Delete datasource
rs.DeleteItem(ssrsPath);
}
}
}

 

 

Result

image

How to create a folder in SQL Server Reporting Services with PowerShell

If you want to use PowerShell to create a folder in SQL Server Reporting Services use the following script:

PowerShell script

"Set execution policy to [Unrestricted]"
Set-ExecutionPolicy Unrestricted

"Load assembly"
[System.Reflection.Assembly]::LoadFrom("C:\Temp\Ada.Cdf.dll")

$folder = New-Object Ada.Cdf.Deployment.SSRS.Folder
$folder.SSRSWebServiceUrl = "http://localhost/ReportServer/ReportService2005.asmx"
$folder.Name = "ADA Sales Reports"
$folder.Parent = "/"
$folder.Create()

 

 

 

C# Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Ada.Cdf.Deployment.SSRS
{
public class Folder
{
public string SSRSWebServiceUrl { get; set; }
public string _parent = "/";
public string Parent
{
get
{
// Use "/" as default value
string firstCharacter = "/";
if (string.IsNullOrEmpty(_parent))
{
_parent = firstCharacter;
}
// Parent should start with one "/"
_parent = firstCharacter + _parent.TrimStart(firstCharacter.ToCharArray());
return _parent;
}
set
{
_parent = value;
}
}
public string _name = string.Empty;
public string Name
{
get
{
if (string.IsNullOrEmpty(_name))
{
_name = string.Empty;
}
// FolderName should not start with"/"
_name = _name.TrimStart("/".ToCharArray());
return _name;
}
set
{
_name = value;
}
}
/// <summary>
/// Create a report
/// </summary>
public void Create()
{
// Validate properties
if (string.IsNullOrEmpty(this.SSRSWebServiceUrl)) { throw new ArgumentNullException("this.SSRSWebServiceUrl"); }
if (string.IsNullOrEmpty(this.Name)) { throw new ArgumentNullException("this.Name"); }
if (string.IsNullOrEmpty(this.Parent)) { throw new ArgumentNullException("this.Parent"); }
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
try
{
rs.
// Create report folder, this will throw an exception if the folder already exists
rs.CreateFolder(this.Name, this.Parent, null);
}
catch (Exception ex)
{
Global.Logger.Info("Folder already exists", ex);
}
}
/// <summary>
/// Delete a report
/// </summary>
public void Delete()
{
// Initialize webservice proxy
ReportService2005.ReportingService2005 rs = new ReportService2005.ReportingService2005();
rs.Url = this.SSRSWebServiceUrl;
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Determine full SSRS path
string ssrsPath = string.Format("{0}/{1}", this.Parent.TrimStart("/".ToCharArray()), this.Name);
// Delete report
rs.DeleteItem(ssrsPath);
}
}
}

Result

image

Explaining SSRS datasource options “Use as Windows credentials when connecting to the datasource” and “Impersonate the authenticated user after a connection has been made to the datasource”

In SSRS ther are two options you can set, when the credentials of the datasource are stored securely in the report server:

  • Use as Windows crendentials when connecting to the datasource

This option must be checked, when you want to use “Windows Integrated Security Authentication” and not “SQL Authentication”

  • Impersonate the authenticated user after a connection has been made to the datasource

This option must be checked, when you want to use the current user to query the database, instead of the given account. The given account is used to connect to the database, but after the connection has been made, the current user is used to query the database. If the current user does not have permissions an exception will occur.

image

How to make sure the first character of a string is one slash ‘/’ with C#, use the TrimStart function

If you want to make sure the first character of a string is one slash, use the function:

public string PrependPath(string path, string firstCharacter)
{
    return firstCharacter + path.TrimStart(firstCharacter.ToCharArray());
}

 

To test the function use:

string firstCharacter = "/";
Console.WriteLine(PrependPath("TestPath", firstCharacter));
Console.WriteLine(PrependPath("/TestPath", firstCharacter));
Console.WriteLine(PrependPath("//TestPath", firstCharacter));
Console.WriteLine(PrependPath("///TestPath", firstCharacter));    

 

Result

/TestPath

/TestPath

/TestPath

/TestPath

How to determine if a local user is member of a local computer group before adding, with PowerShell and C#

To dermine if a local user is member of a local group, before adding the user to the local group in PowerShell I use a C# class. The C# class could be converted to pure PowerShell code, but I prefer the C# class with it’s using statements:

 

[PowerShell script]

"Set execution policy to [Unrestricted]"
Set-ExecutionPolicy Unrestricted

$ComputerName = "."
$ServiceAccountWebUserName = "\saWeb",

"Check if user is member of IIS_IUSRS"
$localGroup = New-Object Ada.Cdf.Deployment.LocalGroup
$localGroup.ComputerName = $ComputerName
$localGroup.Name = "IIS_IUSRS"
if(!$localGroup.ContainsUser($ServiceAccountWebUserName))
{
    "Add user to the IIS_IUSRS group"
    $localGroup.AddUser($ServiceAccountWebUserName)
}

[C# Class]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.Collections;
namespace Ada.Cdf.Deployment
{
public class LocalGroup
{
/// <summary>
/// Name of the computer use "." for executing computer
/// </summary>
string _computerName = Environment.MachineName;
public string ComputerName 
{
get
{
if (!string.IsNullOrEmpty(_computerName) && _computerName.Equals("."))
{
_computerName = Environment.MachineName;
}
return _computerName;
}
set
{
_computerName = value;
}
}
public string Name { get; set; }
/// <summary>
/// 
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public bool ContainsUser(string userName)
{
// Validate properties
if (string.IsNullOrEmpty(this.ComputerName)) { throw new ArgumentNullException("this.ComputerName"); }
if (string.IsNullOrEmpty(this.Name)) { throw new ArgumentNullException("this.Name"); }
bool result = false;
using (DirectoryEntry groupEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1},group", this.ComputerName, this.Name)))
{
// Get group members
IEnumerable groupMembers = (IEnumerable)groupEntry.Invoke("Members");
// Loop members
foreach (object member in groupMembers)
{
using (DirectoryEntry memberEntry = new DirectoryEntry(member))
{
if (memberEntry.Name.ToLower().Equals(userName.ToLower()))
{
result = true;
}
}
}
}
return result;
}
/// <summary>
/// Add a local user to a local group
/// </summary>
/// <param name="userName"></param>
public void AddUser(string userName)
{
// Validate properties
if (string.IsNullOrEmpty(this.ComputerName)) { throw new ArgumentNullException("this.ComputerName"); }
if (string.IsNullOrEmpty(this.Name)) { throw new ArgumentNullException("this.Name"); }
using (DirectoryEntry groupEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1},group", this.ComputerName, this.Name)))
{
// Add user to group
groupEntry.Invoke("Add", new object[] { string.Format("WinNT://{0}/{1}", this.ComputerName, userName) });
}
}
}
}

# How to list members of the local computer group [IIS_IUSRS] with PowerShell

If you want to list all members of the local computer group IIS_IUSRS with PowerShell, use this script:

 

[Script]

"Set execution policy to [Unrestricted]"
Set-ExecutionPolicy Unrestricted

$iisIUSRS = [ADSI]"WinNT://L014/IIS_IUSRS,group"

"Loop members"
foreach ($member in $iisIUSRS.Invoke("Members", $null))
{
    # Cast object to type DirectoryEntry
    $de = New-Object System.DirectoryServices.DirectoryEntry($member)
    # Determine username
    $userName = $de.Name
    # Show the username
    "Member is $userName"
}

 

[Result]

PS C:\Temp> C:\Temp\Test.ps1
Set execution policy to [Unrestricted]
Loop members
Member is SQLServerReportServerUser$L001$MSRS10.MSSQLSERVER
Member is Administrator
Member is saAsaWeb

How to call a PowerShell script with named parameters from a PowerShell (*.ps1) script

If you want to call a PowerShell script (Test2.ps1) with named parameters from a PowerShell script (Test1.ps1), you can’t use the & operator, like & “C:\Temp\Test2.ps1” –Computer L001 –User User1, because the & command is an alias for the Get-Command cmdlet. The Get-Command cmdlet executes precisely one command, see : http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-12-command-discovery-and-scriptblocks.aspx#the-call-operator-quotampquot, but you can use script blocks to execute more then one command or the Invoke-Expression cmdlet. I used the Invoke-Expression cmdlet to call a PowerShell script with named parameters from an other PowerShell script.

[Test1.ps1]

$command = “C:\Temp\Test2.ps1” –Computer L014 –User User1

Invoke-Expression $command

 

 

[Test2.ps1]

param
(
    [string]$Computer = "MyDefaultComputer",
    [string]$User = "MyDefaultUser"

)

$Computer

$User

 

 

[Result]

L014

User1

To combine, format, join or concat strings in PowerShell

You can concat strings in PowerShell by using the + operator, but like in C#, I think it is better to use a formatting approach by using the –f string operator:

 

[-f operator]

PS C:\Users\rLisdonk> "My computer {0} has {1} MB of memory." -f "L001", "4096"
My computer L001 has 4096 MB of memory.

 

[Double quoted string with variables]

You could also use variables in the double quoted string, like:

$myComputer = “L001”

$memory = “4096”

PS C:\Users\rLisdonk> "My computer $myComputer has $memory MB of memory."

 

[+= operator]

You could also use += operator to concat strings

PS C:\Users\rLisdonk> $test = "This is a "
PS C:\Users\rLisdonk> $test += "test string"
PS C:\Users\rLisdonk> $test
This is a test string

 

[Escape characters]

see http://www.techotopia.com/index.php/Windows_PowerShell_1.0_String_Quoting_and_Escape_Sequences