I have a TeamCity build solution with managed (C#) and unmanaged (C++) projects. Is there a TeamCity utility out there similar to Assembly Info Patcher that will change the version numbers in the .rc files for unmanaged C++ DLL and OCX projects to match the build number?
Here's an alternative to StampVer that I ended up doing in PowerShell, which modifies the .rc files prior to the build. I wasn't comfortable with the StampVer constraints of pre-filling the version strings with sufficient space.
#################################################################
#
# Patch all of the given *.rc files and set
# the version strings for DLLs and OCX controls.
#
#################################################################
# Hand parse the arguments so we can separate them with spaces.
$files = #()
$previousArg = "__"
foreach ($arg in $args)
{
if ($previousArg -eq "-version")
{
$version = $arg
}
elseif ($previousArg -eq "__")
{
}
else
{
$files += $arg
}
$previousArg = $arg
}
Function PatchRCFiles([string]$version, [string[]]$files)
{
# check the version number
if ( $version -match "[0-9]+.[0-9]+.[0-9]+.[0-9]+" )
{
echo "Patching all .rc files to version $version"
# convert the version number to .rc format
$rc_version = $version -replace "\.", ","
$rc_version_spaced = $version -replace "\.", ", "
# patch the files we found
ForEach ($file In $files)
{
echo "Processing $file..."
$content = (Get-Content $file)
$content |
Foreach-Object {
$_ -replace "^\s*FILEVERSION\s*[0-9]+,[0-9]+,[0-9]+,[0-9]+$", " FILEVERSION $rc_version" `
-replace "^\s*PRODUCTVERSION\s*[0-9]+,[0-9]+,[0-9]+,[0-9]+$", " PRODUCTVERSION $rc_version" `
-replace "(^\s*VALUE\s*`"FileVersion`",\s*)`"[0-9]+,\s*[0-9]+,\s*[0-9]+,\s*[0-9]+`"$", "`$1`"$rc_version_spaced`"" `
-replace "(^\s*VALUE\s*`"ProductVersion`",\s*)`"[0-9]+,\s*[0-9]+,\s*[0-9]+,\s*[0-9]+`"$", "`$1`"$rc_version_spaced`""
} |
Set-Content $file
}
}
else
{
echo "The version must have four numbers separated by periods, e.g. 5.4.2.123"
}
}
PatchRCFiles $version $files
The configuration in TeamCity then looks like this:
Just give the script a list of .rc files you want to tweak. This step must be run prior to the main build steps.
No, teamcity doesn't have anything to update version of C++ dlls, you could however use StampVer.exe to update the version of C++ dlls. You'll need to download the exe and add a build to call the exe which will update the version of the C++ exe or dll.
Related
I would like to modify this script if possible:
((Get-Content -path "C:\Users\User1\OUT\Summary.txt" -Raw) -replace '</ab></cb>','</x>') | Set-Content -Path "C:\Users\User1\OUT\Summary.txt"
I would like a script that will run with Windows OS to search through one file it finds at this path:
C:\Users\User1\File\Summary.txt
And within that file, when it finds data starting with: <a><b>Data
And at the same time ending with: </ab></cb>
It would need to change the ending to: </x>
And it would need to save the file without changing the name of the file.
For instance a line showing this data:
<a><b>Data:</y> 12345678</ab></cb>
Would be changed to:
<a><b>Data:</y> 12345678</x>
The PowerShell script above will find all instances of </ab></cb> and replace it with </x>, which is not what I am hoping to accomplish.
You can use Get-Content to process the file line be line and only do the Replace when you have a Match on <a><b>. Something like this:
$InFile = ".\TestIn.txt"
$OutFile = ".\TestOut.txt"
If (Test-Path -Path $OutFile) {Remove-Item $OutFile}
Get-Content $InFile | ForEach-Object -Process {
$NewLine = $_
If ($_ -Match '<a><b>') {
$NewLine = ($_ -Replace '</ab></cb>','</x>')
}
Add-Content $OutFile $NewLine
}
#Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
#step 1) Installing Chocolatey when needed
if (-not (Test-Path -Path "$env:ProgramData\Chocolatey\choco.exe" -PathType Leaf))
{
# from https://chocolatey.org/install
Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
# Step 2) defining the array of packages which we want to install
$Packages = 'googlechrome',
'firefox',
'codeblocks',
'windbg',
'x64dbg.portable',
'visualstudio2019community',
'nasm',
'explorersuite',
'pestudio',
'vscode',
'sysinternals',
'python',
'ccleaner',
'anaconda3',
'wireshark',
'sublimetext3',
'notepadplusplus',
'ida-free'
# Step 3) defining the Show-Menu function
function Show-Menu
{
Clear-Host
Write-Host "**********************************************"
Write-Host "LIST OF SOFTWARES"
# writing the options using the array of packages
for ($i = 0; $i -lt $Packages.Count; $i++)
{
# {0,10} means right align with spaces to max 10 characters
Write-Host ('{0,10}. {1}' -f ($i + 1), $Packages[$i])
}
Write-Host " q. Exit the script"
Write-Host "*************************************************"
Write-Host
}
# Step 4) enter an endless loop you only exit if the user enters 'q'
while ($true)
{
Show-Menu
$UserInput = Read-Host "Select the softwares number(s) to be installed (space separated)"
# testing if the user wants to quit and if so, break the loop
if ($UserInput -eq 'q')
{
break
}
foreach($input in $UserInput.Split(' '))
{
# testing if the user entered a number between 1 and the total number of packages (inclusive)
if ([int]::TryParse($input,[ref]$null) -and 1..$Packages.Count -contains [int]$input)
{
# here you install the chosen package using the array index number (= user input number minus 1)
$packageIndex = [int]$input - 1
Write-Host "Installing $($Packages[$packageIndex])"
Choco install $Packages[$packageIndex] -y --ignore-checksums
############## Creating Desktop shortcut ######################
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Desktop\ccleaner.lnk")
$Shortcut.TargetPath = "C:\Program Files\WIndowApps\ccleaner\ccleaner.exe"
$Shortcut.Save()
}
else
{
$availableOptions = 1..$Packages.Count -join ','
Write-Host "Error in selection, choose $availableOptions or q" -ForegroundColor Red
}
}
$null = Read-Host "Press Enter to continue"
}
I have created desktop shortcuts of the software to be installed but instead of writing manually for every application as filename.lnk is their any other way of doing so that as soon as software is installed software shortcut has to created on desktop.
Creating separate function for shortcut and calling the shortcut function
I have SharePoint 2010 environment. Many documents are checked out by other users.
I need to bulk check-in those documents. Can anyone suggest to me a reliable way for the same?
Thanks
You could try below PowerShell.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Variables
$WebURL="http://domain/sites/emilytest"
$LibraryURL="/Shared%20Documents" #Relative URL of a folder or library
#Get Objects
$Web = Get-SPWeb $WebURL
$Folder = $web.GetFolder($LibraryURL)
#Function to find all checked out files in a SharePoint library
Function CheckIn-CheckedOutFiles($Folder)
{
$Folder.Files | Where { $_.CheckOutStatus -ne "None" } | ForEach-Object {
write-host ($_.Name,$_.URL,$_.CheckedOutBy)
#To Check in
$_.Checkin("Checked in by Administrator")
}
#Process all sub folders
$Folder.SubFolders | ForEach-Object {
CheckIn-CheckedOutFiles $_
}
}
#Call the function to find checkedout files
CheckIn-CheckedOutFiles $Folder
I've got a PowerShell script that I call from VBA using Excel. The script uses WinSCP to download some datetime-named FTP and SFTP files and saves them with a static filename, overwriting the old file, on a network drive location.
The script works on first run, but after that it loads the same cached version of the file. The workaround is to change the cache settings in IE to check for newer versions of stored webpages 'every time I visit the webpage'.
The macro is used by several people and is accessed using a variety of computers. Is there a way around this that I can incorporate in my code, either in VBA or PS so they don't have to remember to go into IE to change their settings?
Script is called from VBA:
Call Shell("powershell -executionpolicy bypass & ""H:\FTP\FTP.ps1""", vbHide)
Script:
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
$localPath = "H:\Worksheets\FTP"
$remotePath = "/outgoing/data/LatestData/"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::ftp
$sessionOptions.HostName =
$sessionOptions.UserName =
$sessionOptions.Password =
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Get list of files in the directory
$directoryInfo = $session.ListDirectory($remotePath)
# Select the most recent file
$latest = $directoryInfo.Files |
Where-Object { -Not $_.IsDirectory} |
Where-Object {
[System.IO.Path]::GetExtension($_.Name) -eq ".nc1" -or
[System.IO.Path]::GetExtension($_.Name) -eq ".ky1" -or
[System.IO.Path]::GetExtension($_.Name) -like ".tn*" }
Group-Object { [System.IO.Path]::GetExtension($_.Name) } |
ForEach-Object{
$_.Group | Sort-Object LastWriteTime -Descending | Select -First 1
}
$extension = [System.IO.Path]::GetExtension($latest.Name)
"GetExtension('{0}') returns '{1}'" -f $fileName, $extension
if ($latest -eq $Null)
{
Write-Host "No file found"
exit 1
}
$latest | ForEach-Object{
$extension = ([System.IO.Path]::GetExtension($_.Name)).Trim(".")
$session.GetFiles($session.EscapeFileMask($remotePath + $_.Name), "$localPath\$extension.txt" ).Check()
}
$stamp = $(Get-Date -f "yyyy-MM-dd-HHmm")
$filename = $stamp.subString(0,$stamp.length-6)
$session.GetFiles(
($remotePath + $fileName),
($localPath + $fileName + "." + $stamp)).Check()
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
I'm trying to build a file path in PowerShell and the string concatenation seems to be a little funky.
I have a list of folders:
c:\code\MyProj1
c:\code\MyProj2
I want to get the path to a DLL file here:
c:\code\MyProj1\bin\debug\MyProj1.dll
c:\code\MyProj2\bin\debug\MyProj2.dll
Here's what I'm trying to do:
$buildconfig = "Debug"
Get-ChildItem c:\code | % {
Write-Host $_.FullName + "\" + $buildconfig + "\" + $_ + ".dll"
}
This doesn't work. How can I fix it?
Try this
Get-ChildItem | % { Write-Host "$($_.FullName)\$buildConfig\$($_.Name).dll" }
In your code,
$build-Config is not a valid variable name.
$.FullName should be $_.FullName
$ should be $_.Name
You could use the PowerShell equivalent of String.Format - it's usually the easiest way to build up a string. Place {0}, {1}, etc. where you want the variables in the string, put a -f immediately after the string and then the list of variables separated by commas.
Get-ChildItem c:\code|%{'{0}\{1}\{2}.dll' -f $_.fullname,$buildconfig,$_.name}
(I've also taken the dash out of the $buildconfig variable name as I have seen that causes issues before too.)
Try the Join-Path cmdlet:
Get-ChildItem c:\code\*\bin\* -Filter *.dll | Foreach-Object {
Join-Path -Path $_.DirectoryName -ChildPath "$buildconfig\$($_.Name)"
}
This will get all dll files and filter ones that match a regex of your directory structure.
Get-ChildItem C:\code -Recurse -filter "*.dll" | where { $_.directory -match 'C:\\code\\myproj.\\bin\\debug'}
If you just want the path, not the object you can add | select fullname to the end like this:
Get-ChildItem C:\code -Recurse -filter "*.dll" | where { $_.directory -match 'C:\\code\\myproj.\\bin\\debug'} | select fullname