I'm trying to automate some of the tasks I perform on each web project. What I want is a PoSH script that I can run on a new solution that will:
load the solution contained in the scripts current directory.
create new projects for the loaded solution and add them to the solution.
create some classes and add them to each of the projects.
So far I have a simple script (shown below) that finds and opens the local solution file.
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
Set-Location $dir
$solution = Get-ChildItem | Where-Object{($_.Extension -eq ".sln")}
if ($solution.Count -eq 0)
{
"Please place this script in the folder containing you solution file."
break;
}
$dteObj = New-Object -ComObject "VisualStudio.DTE"
$dteObj.Solution.Open($solution.FullName)
How can I now create new projects and add them to the solution?
Check out http://studioshell.codeplex.com/ by Jim Christopher.
To create a project , call GetProjectTemplate, and then pass the returned template paths to AddFromTemplate.
Try this in Package Manager Console.
#Create a Console Project
$csTemplatePath = $dte.Solution.GetProjectTemplate("ConsoleApplication.zip", "CSharp")
$csPrjPath = "C:\\Projects\\SolutionName\\ConsoleApplication1"
$dte.Solution.AddFromTemplate($csTemplatePath, $csPrjPath, "ConsoleApplication1", 'false')
#Create a C# class
$itemPath = $dte.Solution.GetProjectItemTemplate("Class.zip", "CSharp")
$prj = Get-Project
$prjItem = $prj.ProjectItems.AddFromTemplate($itemPath, "Project.cs")
Related
I am running a vsts build inline PowerShell script task to create package for Azure cloud service. It works fine and create package file from my local machine, but when I try to run from VSTS PowerShell inline task it gives error :
##[error]Cannot find path ‘D:\a_tasks\InlinePowershell_31f040e5-e040-4336-878a-59a493355534\1.1.6\ServiceConfiguration.Cloud.Test.cscfg’ because it does not exist.
Here is my PowerShell inline script below, It fails on the following line:
Copy-Item $serviceConfigurationPath $packageOutDir
I really appreciate your help on this.
Thanks,
# This is the VSTS repository path
$workingDirectory = “$/DevCodeBase/ToolDevBranch1.33”
$webProjectName = “WebRole1”
$cloudProjectName = ‘ProjAzureDeployment’
$evv =’Test’
$cppack = ‘C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\cspack.exe’
$solutionDir = [string]::Format(“{0}”, $workingDirectory)
$webDir = [string]::Format(“{0}\{1}”, $workingDirectory, $webProjectName)
$packageOutDir = [string]::Format(“{0}\{1}”, $workingDirectory, $cloudProjectName)
$rolePropertyFile = [string]::Format(“{0}\{1}\{2}”, $workingDirectory, $cloudProjectName, “roleproperties.txt”)
# Create Role Properties File – This property file specifies the .Net framework against which webrole is going to run.
New-Item $rolePropertyFile -Type file -Force -Value “TargetFrameWorkVersion=v4.5” | Out-Null
New-Item $packageOutDir -Type directory -Force | Out-Null
# CSPack command Definition
$serviceDefinitionPath = [string]::Format(“{0}\{1}\ServiceDefinition.csdef”, $solutionDir, $cloudProjectName)
if ($evv -eq “Test”){
$serviceConfigurationPath = “ServiceConfiguration.Cloud.Test.cscfg”
}
else
{
$serviceConfigurationPath = [string]::Format(“{0}\{1}\ServiceConfiguration.Cloud.cscfg”, $solutionDir, $cloudProjectName)
}
$serviceRole = [string]::Format(“/role:{0};{1}”, $webProjectName, $webDir)
$rolePropertiesFile = [string]::Format(“/rolePropertiesFile:{0};{1}”, $webProjectName, $rolePropertyFile)
$sites = [string]::Format(“/sites:{0};Web;{1}”, $webProjectName, $webDir)
$packageOutput = [string]::Format(“/out:{0}\{1}.cspkg”, $packageOutDir, $cloudProjectName)
# $packageOutput = [string]::Format(“{0}\{1}.cspkg”, $packageOutDir, $cloudProjectName)
Write-Host $packageOutput
Write-Host $serviceConfigurationPath
# Build CSPKG file
& “C:\Program Files\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\cspack.exe” $serviceDefinitionPath $serviceRole $rolePropertiesFile $sites $packageOutput /useCtpPackageFormat | Out-Null
Write-Host $serviceDefinitionPath
Write-Host $serviceRole
Write-Host $rolePropertiesFile
Write-Host $sites
Write-Host $packageOutput
Write-Host ‘before copy’
# Copy configuration file
Copy-Item $serviceConfigurationPath $packageOutDir
# Remove Role Properties File
Remove-Item -Path $rolePropertyFile -Force | Out-Null
In the VSTS task you'll have to specify an absolute path, otherwise the script will look in the temporary directory created for your inline powershell script.
For instance, you could supply the path to the file as a parameter like
-filepath "$(System.DefaultWorkingDirectory)\Solution\config.json"
(For a list of the variables you can use, have a peek here)
If you want to keep using a relative path, you can move to a file based (ie non-inline) script and use a relative path to that.
I'm Trying to copy Mail Items from one mailbox to another, but when i use the Folder.Copy Method to copy the Inbox folder of one mailbox to the other, it's not merge the data but creating Folder Named Inbox1,
Here's my code:
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace("mapi")
$namespace.Logon("Outlook")
$LocalStore = $Namespace.Stores[3]
$RemoteStore = $Namespace.Stores[1]
$LocalFolders = $LocalStore.GetRootFolder().folders
$RemoteFolders = $RemoteStore.GetRootFolder().folders
$RemoteInbox = $RemoteFolders | ? {$_.Name -eq "Inbox"}
$LocalInbox = $LocalFolders | ? {$_.Name -eq "Inbox"}
$RemoteInbox.CopyTo($LocalInbox.Parent)
To workaround i can use the Items Copy :
Foreach ($Item in $RemoteInbox.Items)
{
$Copy = $Item.Copy()
[void]$Copy.Move($TargetFolder)
}
But it's much slower, and if i have subfolders it need special care with extra code,
Search the web with no solution found
Any help is appreciated
This is to be expected - if there is already an existing folder with the same name, MAPI will return MAPI_E_COLLISION - see IMAPIFolder::CopyFolder.
Outlook detects that error and creates a folder with a unique name.
You can copy items in a batch using IMAPIFolder.CopyMessages, but Extended MAPI requires C++ or Delphi. If using Redemption is an option (I am its author), you can use its RDOItems.CopyMultiple method. You can create an array of entry ids from the source folder using RDOItems.MAPITable.ExecSQL and pass it to RDOItems.CopyMultiple.
I want to create a nuget package which will run a Powershell script on restore in a C# project. The script will change the values of the project properties on the project e.g.:
Set value of
<AssemblyVersion>1.0.0.0</AssemblyVersion>
to
<AssemblyVersion>$(ReleaseApplicationVersion)</AssemblyVersion>
and some other properties.
Thanks in advance!
UPDATE-------------------------------------------
This is what I have
param([string]$projectName = $(throw 'csproj file is required'))
$proj = Resolve-Path $projectName
$propAssemblyName = $proj.Properties.Item("AssemblyName")
$propAssemblyName.Value = '$(ReleasedAssemblyName)'
But I obviously dont know how to make this work as I get bunch of issues. Thanks
function Set-Version {
Write-Header "Updating version in .csproj files"
try {
Push-Location ".\csprojLocation"
$versionProjFile = Resolve-Path "*.csproj"
$xml = [xml](Get-Content $versionProjFile)
$xml.Project.PropertyGroup.AssemblyVersion = ${version}
$xml.Save($versionPropsFile)
}
finally {
Pop-Location
}
}
Set-Version
I have a folder filled with TTF files of custom fonts. I need to install them as system fonts using a powershell script (this is on Windows Server 2008 R2). Does anybody know how to do that in powershell?
Thanks!
It is quite simple. Take a look on the snippet below:
$FONTS = 0x14
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)
$objFolder.CopyHere("C:\test\Myfont.ttf")
And it should not require to restart/logoff...
The 0x14 value is the CLSID of the special folder.
In addition I just found this tutorial explaining each step above:
http://windowsitpro.com/scripting/trick-installing-fonts-vbscript-or-powershell-script
Just wanted to post an alternative which doesn't require 0x14 to be hard coded into the script. Pass the file object to the function, and it will just run the "Install" based on where the file is:
Function Install-Font {
Param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)][System.IO.FileSystemInfo[]]$File
)
$shell = New-Object -ComObject Shell.Application
$File | % {
$Fonts = $shell.NameSpace($_.Directory.Name)
$font = $Fonts.ParseName($_.Name)
$font.InvokeVerb("Install")
}
}
Using the Shell.Application COM object doesn't work on Server Core (at least not on 2012 R2).
I had success by simply copying the font file to C:\Windows\Fonts (in this case times.ttf) and then adding the corresponding registry entry with PowerShell:
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts' -Name 'Times New Roman (TrueType)' -PropertyType String -Value times.ttf
Removal is the reverse of installation. The only downside is that a restart is required both after the font has been installed and also before it is uninstalled if an application has referenced it.
Shell code has been known to fail on Remote and Build agents - if the comobjects using shell are failing and you are vetting via Remote or Build agents then you will need to use the framework classes to do this (reference)
## Add or Remove Font Files - only tested with TTF font files thus far
#<#
#=======================================================================================================
# ADD or REMOVE MULTIPLE FONT FILES [Using ComObjects]
#=======================================================================================================
# This code will install or uninstall a font using ComObject
# You Must Modify the following variables in order to work
# (A) $dirFiles ==> This is the source folder path that contains all of your font files
# (B) $InstallOrUninstall ==> $true = Install Font ... $false = UnInstall Font
#=======================================================================================================
# Define Working Variables
$dirFiles = "C:\Temp\Fonts"
$InstallOrUninstall = $false # $true = Install = 1 ...or... $false = UnInstall = 0
$srcFontFiles = Get-ChildItem "$($dirFiles)\Fonts"
$Fonts = (New-Object -ComObject Shell.Application).Namespace(0x14)
# Copy each file into the Font Folder or Delete it - Depends on the $InstallOrUninstall variable setting
ForEach($srcFontFile in $srcFontFiles)
{
$srcFontFileName = $srcFontFile.name
$srcFontFileFullPath = $srcFontFile.fullname
$targFonts = "C:\Windows\Fonts\$($srcFontFileName)"
If (Test-Path $targFonts -PathType any) { Remove-Item $targFonts -Recurse -Force } # UnInstall Font
If ((-not(Test-Path $targFonts -PathType container)) -and ($InstallOrUninstall -eq $true)) { $fonts.CopyHere($srcFontFileFullPath, 16) } # Install Font
}
#>
I can pin some programs to taskbar on Win7 using PowerShell.
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace('C:\Windows')
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Tas&kbar'}
if ($verb) {$verb.DoIt()}
How do I modify the above code to pin a program to the Start menu?
Another way
$sa = new-object -c shell.application
$pn = $sa.namespace($env:windir).parsename('notepad.exe')
$pn.invokeverb('startpin')
Or unpin
$pn.invokeverb('startunpin')
Use the code below
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace('C:\Windows')
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Start Men&u'}
if ($verb) {$verb.DoIt()}
Note: the change is in the fourth line.
The main problem with most of the solution is that they enumerate the verbs on a file, search for the string to perform the action (“Pin to Startmenu” etc.) and then execute it. This does not work if you need to support 30+ languages in your company, except you use external function to search for the localized command (see answer from shtako-verflow).
The answer from Steven Penny is the first that is language neutral and does not need any external code. It uses the verbs stored in the registry HKEY_CLASSES_ROOT\CLSID\{90AA3A4E-1CBA-4233-B8BB-535773D48449} and HKEY_CLASSES_ROOT\CLSID\{a2a9545d-a0c2-42b4-9708-a0b2badd77c8}
Based on this, here’s the code we are now using:
function PinToTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarpin"
}
function UnpinFromTaskbar {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "taskbarunpin"
}
function PinToStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startpin"
}
function UnpinFromStartmenu {
param([Parameter(Mandatory=$true)][string]$FilePath)
ExecuteVerb $FilePath "startunpin"
}
function ExecuteVerb {
param(
[Parameter(Mandatory=$true)][string]$File,
[Parameter(Mandatory=$true)][string]$Verb
)
$path = [System.Environment]::ExpandEnvironmentVariables($File)
$basePath = split-path $path -parent #retrieve only the path File=C:\Windows\notepad.exe -> C:\Windows
$targetFile = split-path $path -leaf #retrieve only the file File=C:\Windows\notepad.exe -> notepad.exe
$shell = new-object -com "Shell.Application"
$folder = $shell.Namespace($basePath)
if ($folder)
{
$item = $folder.Parsename($targetFile)
if ($item)
{
$item.invokeverb($Verb)
# "This method does not return a value." (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787816%28v=vs.85%29.aspx)
# Therefore we have no chance to know if this was successful...
write-host "Method [$Verb] executed for [$path]"
}
else
{
write-host "Target file [$targetFile] not found, aborting"
}
}
else
{
write-host "Folder [$basePath] not found, aborting"
}
}
#PinToTaskbar "%WINDIR%\notepad.exe"
#UnpinFromTaskbar "%WINDIR%\notepad.exe"
PinToStartmenu "%WINDIR%\notepad.exe"
#UnpinFromStartmenu "%WINDIR%\notepad.exe"
See the script (international) here : http://gallery.technet.microsoft.com/scriptcenter/b66434f1-4b3f-4a94-8dc3-e406eb30b750
If you want to add an action like Pin to Modern UI interface (Windows 8), at $verbs, add 51201
Steven Penny's second answer above worked well for me. Here are a couple more tidbits.
It's doing COM through PowerShell, so you can do the same thing with pretty much any COM client. For example, here's an AutoHotkey version.
Shell := ComObjCreate("Shell.Application")
Target := Shell.Namespace(EnvGet("WinDir")).ParseName("Notepad.exe")
Target.InvokeVerb("startpin")
VBScript or InnoSetup would look almost the same except for the function used to create the object.
I also found that I have one program that pinned OK, but didn't have the right icon and/or description because of limitations in the compiler. I just made a little 1-line WinForms app that starts the target with Process.Start, and then added the appropriate icon, and the name I wanted in the Start Menu in the Title property in AppInfo.cs.