How can I have a Windows Service, installed using OctopusDeploy, use an app.config? - asp.net

So far, I've been able to create a Windows Service, which I can then get TeamCity to build and pack up and make available for Octopus Deploy.
What I can't seem to do, is have an app.config which has a connection string in it and use that connection string.
The following is my Deploy.ps1:
# These variables should be set via the Octopus web portal:
#
# ServiceName - Name of the Windows service
#
# sc.exe is the Service Control utility in Windows
# Default the service name
if (! $ServiceName)
{
$ServiceName = "OctoService"
}
Write-Host "Service Name:" $ServiceName
# Get the exe name based ont the directory
$contentPath = (Join-Path $OctopusPackageDirectoryPath "content")
$configName = (Get-ChildItem $contentPath\*.config -Name | Select-Object -First 1)
$binPath = (Join-Path $OctopusPackageDirectoryPath "lib\net40")
$exeName = (Get-ChildItem $binPath\*.exe -Name | Select-Object -First 1)
$fullPath = (Join-Path $binPath $exeName)
Write-Host "Service Path:" $fullPath
Write-Host "Config Path:" (Join-Path $contentPath $configName)
Copy-Item (Join-Path $contentPath $configName) $binPath
$service = Get-Service $ServiceName -ErrorAction SilentlyContinue
if (! $service)
{
Write-Host "The service will be installed"
New-Service -Name $ServiceName -BinaryPathName $fullPath -StartupType Automatic
}
else
{
Stop-Service $ServiceName -Force
$fullPath = Resolve-Path $fullPath
& "sc.exe" config "$ServiceName" binPath= $fullPath start= auto | Write-Host
Start-Service $ServiceName
}
Here's my .nuspec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>Copyright 2012</copyright>
</metadata>
<files>
<file src="app.config" target="content" />
<file src="Deploy.ps1" />
</files>
</package>
If I try to access ConfigurationManager.ConnectionStrings["MyConnectionString"], I'll get a null reference.
Any suggestions?

my money is on you needing to name your app.config to exename.exe.config so it is picked up by your service.
App.config is the 'temporary' name used in the ide, it gets renamed as part of the build to whatever the exe name is

Related

How to stop build through dockerfile when unit test failed (Dockerfile + .NET Framework + Nunit Test + Docker Window Container

I have to build stop when unit test fail through docker file. I am using .NET Framework (not Dot.Net Core). I have to write command either in power shell script or Docker file (if Unit test fail then build should be stop before execute next line of docker file.
.NET Framework 4.7.2
Docker Window container only
Unit test project (Nunit)
Asp.Net WebForms (old)
Nunit test runner
Steps,
I have create project for Unit test + WebForm + Class library.
I have created powershell script for run unit test project using Nunit test runner.
I have added path for script in docker file.
I have attached Docker file and power-shell script .
Docker file code here
`# escape=`
FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-20200512-windowsservercore-ltsc2019
WORKDIR /src
COPY ./POC.Web/POC.Web.csproj ./POC.Web/
COPY ./POC.Entites/POC.Entites.csproj ./POC.Entites/
COPY ./POC.Business.Layer/POC.Business.Layer.csproj ./POC.Business.Layer/
COPY ./POC.UnitTests/POC.UnitTests.csproj ./POC.UnitTests/
COPY ./POC.UnitTests/packages.config ./POC.UnitTests/
COPY ./MttcPoc.sln .
RUN nuget restore MttcPoc.sln
COPY . .
RUN msbuild POC.UnitTests/POC.UnitTests.csproj /p:OutputPath=c:/out/tests
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]
# testResult variable using in shellscript to get the result of unit test
ENV testResult="Passed"
RUN nuget install NUnit.Runners
COPY ./startuptest.ps1 /
RUN /startuptest.ps1
#RUN IF $testResult == "Passed" EXIT 0 ELSE EXIT -1
RUN if [ "$testResult" = "Passed" ] ; then true ; else false; fi
ENTRYPOINT ["powershell", "/startuptest.ps1"]
#*****************************************************
#Below line should not execute if unit test fail
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-20200512-windowsservercore-ltsc2019
ENV APP_ROOT=/inetpub/wwwroot `
CONNECTIONSTRINGS_CONFIG_MAP="" `
dockercomposeKey="From Docker file"
WORKDIR ${APP_ROOT}
RUN Import-Module WebAdministration; `
Set-ItemProperty -Path 'IIS:\AppPools\DefaultAppPool' -Name processModel.identityType -Value LocalSystem; `
New-WebApplication -Name 'app' -Site 'Default Web Site' -PhysicalPath $env:APP_ROOT
COPY ./startup.ps1 /
RUN /startup.ps1
#ENTRYPOINT ["powershell", "/startup.ps1"]
COPY --from=build c:/out/_PublishedWebsites/POC.Web ${APP_ROOT}
#************************************************************************`
Powershell script code here
$ProjectDir = "."
$OutDir = "$ProjectDir\testresults"
$testProjectPath = "c:\out\tests\POC.UnitTests.dll"
# Set nunit path test runner
$nunit_path = "$ProjectDir\NUnit.ConsoleRunner.3.11.1\tools\nunit3-console.exe"
# Run NUnit3 tests
& $nunit_path $testProjectPath --framework=net-4.7.2 --work=$OutDir
[XML]$resultDetails = Get-Content .\$OutDir\TestResult.xml
Write-Output $resultDetails
$string = "test-run"
Write-Output $resultDetails.$string.result
$env:testResult = $resultDetails.$string.result
#Passed
#Failed
#Below line added for if test fail then exit from docker build
If ($resultDetails.$string.result -eq 'Passed') {
Write-Output "Test passed"
Write-Output $env:testResult
return true
}else{
Write-Output "Test failed"
Write-Output $env:testResult
return -1
}

MSB4018 Error Visual Studio 2015 ASP.Net and Error Publish Web App to Azure

I am working with Visual Studio 2015 Community with Azure 2.9 For the first time. I tried creating a brand new ASP.Net Web Application. The default template build and viewed in the Browser with no issues.
I tried publishing the site using Azure. When doing so I get this error
The "InvokePowerShell" task failed unexpectedly.
System.Management.Automation.CommandNotFoundException: The term '[cmdletbinding(SupportsShouldProcess=$true)]
param($publishProperties, $packOutput, $nugetUrl)
# to learn more about this file visit http://go.microsoft.com/fwlink/?LinkId=524327
$publishModuleVersion = '1.0.1'
function Get-VisualStudio2015InstallPath{
[cmdletbinding()]
param()
process{
$keysToCheck = #('hklm:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0',
'hklm:\SOFTWARE\Microsoft\VisualStudio\14.0',
'hklm:\SOFTWARE\Wow6432Node\Microsoft\VWDExpress\14.0',
'hklm:\SOFTWARE\Microsoft\VWDExpress\14.0'
)
[string]$vsInstallPath=$null
foreach($keyToCheck in $keysToCheck){
if(Test-Path $keyToCheck){
$vsInstallPath = (Get-itemproperty $keyToCheck -Name InstallDir -ErrorAction SilentlyContinue | select -ExpandProperty InstallDir -ErrorAction SilentlyContinue)
}
if($vsInstallPath){
break;
}
}
$vsInstallPath
}
}
$vsInstallPath = Get-VisualStudio2015InstallPath
$publishModulePath = "{0}Extensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
if(!(Test-Path $publishModulePath)){
$publishModulePath = "{0}VWDExpressExtensions\Microsoft\Web Tools\Publish\Scripts\{1}\" -f $vsInstallPath, $publishModuleVersion
}
$defaultPublishSettings = New-Object psobject -Property #{
LocalInstallDir = $publishModulePath
}
function Enable-PackageDownloader{
[cmdletbinding()]
param(
$toolsDir = "$env:LOCALAPPDATA\Microsoft\Web Tools\Publish\package-downloader-$publishModuleVersion\",
$pkgDownloaderDownloadUrl = 'http://go.microsoft.com/fwlink/?LinkId=524325') # package-downloader.psm1
process{
if(get-module package-downloader){
remove-module package-downloader | Out-Null
}
if(!(get-module package-downloader)){
if(!(Test-Path $toolsDir)){ New-Item -Path $toolsDir -ItemType Directory -WhatIf:$false }
$expectedPath = (Join-Path ($toolsDir) 'package-downloader.psm1')
if(!(Test-Path $expectedPath)){
'Downloading [{0}] to [{1}]' -f $pkgDownloaderDownloadUrl,$expectedPath | Write-Verbose
(New-Object System.Net.WebClient).DownloadFile($pkgDownloaderDownloadUrl, $expectedPath)
}
if(!$expectedPath){throw ('Unable to download package-downloader.psm1')}
'importing module [{0}]' -f $expectedPath | Write-Output
Import-Module $expectedPath -DisableNameChecking -Force
}
}
}
function Enable-PublishModule{
[cmdletbinding()]
param()
process{
if(get-module publish-module){
remove-module publish-module | Out-Null
}
if(!(get-module publish-module)){
$localpublishmodulepath = Join-Path $defaultPublishSettings.LocalInstallDir 'publish-module.psm1'
if(Test-Path $localpublishmodulepath){
'importing module [publish-module="{0}"] from local install dir' -f $localpublishmodulepath | Write-Verbose
Import-Module $localpublishmodulepath -DisableNameChecking -Force
$true
}
}
}
}
try{
if (!(Enable-PublishModule)){
Enable-PackageDownloader
Enable-NuGetModule -name 'publish-module' -version $publishModuleVersion -nugetUrl $nugetUrl
}
'Calling Publish-AspNet' | Write-Verbose
# call Publish-AspNet to perform the publish operation
Publish-AspNet -publishProperties $publishProperties -packOutput $packOutput
}
catch{
"An error occurred during publish.`n{0}" -f $_.Exception.Message | Write-Error
}' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.PowerShell.EndInvoke(IAsyncResult asyncResult)
at Microsoft.Web.Publishing.Tasks.InvokePowerShell.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() WebApplication1 0
I am assuming I missed something in my install? Anyone know what this error is or how to get passed it?
I upvoted this in the past, then apparently found the answer somewhere else, then forgot the answer again and ended up here again.
Adding <AutoParameterizationWebConfigConnectionStrings>False</AutoParameterizationWebConfigConnectionStrings>
in the csproj on the right PropertyGroup fixed the problem for me.

Problems when configuring Advance IIS logs with Powershell

The objectives of this script:
Create a new folder for each site
Create one log per site per day
A second script to backup/arhive scripts within a certain format
Stop all normal logging
# Ensure cmdlets are available
Import-Module WebAdministration
$Websites = (Get-Website).Name
foreach($site in $websites)
{
Stop-Website $site
}
# Disables http logging module
Set-WebConfigurationProperty -Filter system.webServer/httpLogging -PSPath
machine/webroot/apphost -Name dontlog -Value true
# Disables the default advanced logging config
Set-WebConfigurationProperty -Filter "system.webServer/advancedLogging/server
/logDefinitions/logDefinition[#baseFileName='%COMPUTERNAME%-Server']" -name
enabled -value false
# Enable Advanced Logging
Set-WebConfigurationProperty -Filter system.webServer/advancedLogging/server
-PSPath machine/webroot/apphost -Name enabled -Value true
# Move to location to store iis logs
cd C:\inetpub\Logs\Advancedlogs
# Create Folders if required
Foreach($site in $websites)
{
$FoldersPresent = Test-Path "C:\inetpub\logs\AdvancedLogs\$site"
if($FoldersPresent -eq $true)
{
Write-host "Folder exsists"
}
else
{
New-Item -ItemType directory $site
}
}
# Create hash table
$list = #{'Win32Status'='sc-win32-status';'URI-Stem'='cs-uri-stem';
'URI-Querystring'='cs-uri-query';'Time-UTC'='time';'Time-Local'='time-
local';'Take Taken'='TimeTakenMS';'Substatus'='sc-substatus';'Status'='sc-
status';'Site Name'='s-sitename';'Server-IP'='s-ip';'Server Port'='s-port';
'Server Name'='s-computername';'Protocol Version'='cs-version';'Protocol'='c-
protocol';'Method'='cs-method';'Date-UTC'='date';'Date-Local'='date-local';
'ContentPath'='s-contentpath';'Client-IP'='c-ip';'EndRequest-UTC'='EndRequest-
UTC';'Bytes Sent'='sc-bytes';'Bytes Received'='cs-bytes';'BeginRequest-
UTC'='BeginRequest-UTC';'UserName'='cs-username';'User Agent'='cs(User-
Agent)';'Referer'='cs(Referer)';'Proxy'='s-proxy';'Host'='cs(Host)';
'Cookie'='cs(Cookie)'}
# Set the log file fields
foreach($site in $Websites)
{
$AppName = $site
$appdrive = "C:\inetpub\logs\AdvancedLogs\$site"
$LogRotateFreq = "Daily"
Add-WebConfiguration /system.webServer/advancedLogging/Server
/logDefinitions IIS:\ -Location $AppName -value
#{baseFileName="%COMPUTERNAME%-$AppName";enabled="true";
logRollOption="Schedule";schedule=$LogRotateFreq;publishLogEvent="false"}
$list.GetEnumerator() | foreach {
Add-WebConfiguration "/system.webServer/advancedLogging/Server/logDefinitions/logDefinition[#baseFileName=""%COMPUTERNAME%-$AppName""]/selectedFields" IIS:\ -Location $AppName -value #{defaultValue="";required="false";logHeaderName=$_.Name;id=$_.Value;}
Set-WebConfiguration "/system.applicationHost/Sites/Site[#name=""$AppName""]/advancedLogging" -value #{directory="$appdrive"}
}
}
# Start the websites
foreach($site in $websites)
{
Start-Website $site
}
Links used for guidance:
http://forums.iis.net/t/1185802.aspx?No+log+files+created+by+Advanced+Logging
http://forums.iis.net/t/1193633.aspx?Configure+Advanced+Logging+through+powershellhttp://www.antonyfrancis.net/2014/01/automated-installation-and.html

After Deploying mywebsite to server can I encrypt the web.config file?

I am trying to encrypt the web.config file after deploying automatically.
As per the Link :https://blogs.iis.net/msdeploy/archive/2013/07/09/webdeploy-3-5-rtw.aspx
I am using below command:
msdeploy.exe –verb:sync –source:iisapp=”sourceTestSite” –dest:iisapp=”destinationTestSite” –EnableRule:EncryptWebConfig
But then I am getting error:
Error Code: ERROR_FAILED_TO_ENCRYPT_WEB_CONFIG
I do not want to first encrypt and then deploy. I am thinking to run deployment script and after deployment it should encrypt automatically probably using MSDEploy command.
I tried below threads but did not get any help:
Failed to encrypt destination web.config when using MS build plugin in Jenkins
Also I wanted to keep my secret file in separate location but I found encryption process will not work for that
How to encrypt a file linked to a web.config
This time I am trying to run command on remote server to encrypt the web.config file by using below code. I am running below code in my machine and trying to encrypt the web.config file present on my myRemoteServer.
$currentDirectory = (Get-Location)
$user = "domain1\username1"
$section = "appSettings"
$app= "/MyWeb"
$version="v4.0.30319"
$computername ="myRemoteServer"
$pwd = ConvertTo-SecureString -String "mysecret#11" -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user,$pwd
$encryptcmd1= Set-Location "C:\windows\Microsoft.Net\Framework\$version"
$encryptCmd2 = ".\aspnet_regiis.exe -pe ""appSettings"" -app ""/MyWeb"""
$encryptCmd = "$encryptcmd1 $encryptcmd2"
try
{
invoke-command -ComputerName $computername -Credential $credential -ScriptBlock {$encryptCmd}
}
catch
{
Log-Message $_
}
Set-Location $currentDirectory
It doesn't throw any exception. However it is not working and not encrypting web.config file on that server.
I want to know where / what is wrong here.
his function will encrypt a sections of a web.config file.
function Encrypt-ConfigurationSection([int] $id, [string] $app, [string] $section, [string] $version){
$currentDirectory = (Get-Location)
Set-Location "C:\windows\Microsoft.Net\Framework\$version\"
.\aspnet_regiis.exe -pe $section -app $app -site $id -prov "RsaProtectedConfigurationProvider"
Set-Location $currentDirectory
}
Example call
Encrypt-ConfigurationSection 1 ‘/WebApplication1’ ‘connectionStrings’ ‘v4.0.30319’
This function will decrypt a sections of a web.config file.
function Decrypt-ConfigurationSection([int] $id, [string] $app, [string] $section, [string] $version){
$currentDirectory = (Get-Location)
Set-Location "C:\windows\Microsoft.Net\Framework\$version\"
.\aspnet_regiis.exe -pd $section -app $app -site $id
Set-Location $currentDirectory
}
Example Call
Decrypt-ConfigurationSection 1 ‘/WebApplication1’ ‘connectionStrings’ ‘v4.0.30319’
I got help from this website:
https://joshjoubert.wordpress.com/2013/03/28/encrypting-and-decrypting-sections-of-a-web-config-with-powershell/

How Do You Iterate Authentication for App IIS7 In PowerShell

I need to iterate all authentication modes for an IIS Application and disable all except one.
something like:
foreach($itm in [collection of authentication modes for app]){
if([certain authentication]){enabled = true}else{enabled = false}}
I'm familiar with Set-WebConfigurationProperty.
You can iterate all native (as well as any installed third-party) authentication modes for the root web application for a given site by calling Get-WebConfiguration:
$siteName = "MySiteName"
$authentications = Get-WebConfiguration `
-filter "system.webServer/security/authentication/*" `
-PSPath "IIS:\Sites\$siteName"
You can also iterate the authentication modes for any given web application in the site (or even specific file(s)). The following retrieves the authentication modes for a contrived web application called "\foo":
$authentications = Get-WebConfiguration `
-filter "system.webServer/security/authentication/*" `
-PSPath "IIS:\Sites\$siteName\foo"
The SectionPath property can be used to examine the authentication mode, e.g.:
$authentications | foreach {$_.SectionPath}
Which outputs:
/system.webServer/security/authentication/digestAuthentication
/system.webServer/security/authentication/anonymousAuthentication
/system.webServer/security/authentication/iisClientCertificateMappingAuthentication
/system.webServer/security/authentication/basicAuthentication
/system.webServer/security/authentication/clientCertificateMappingAuthentication
/system.webServer/security/authentication/windowsAuthentication
You might think you could do something as simple as this in your foreach loop...
$authentications | `
foreach { $_.Enabled = $_.SectionPath.EndsWith('\windowsAuthentication') }
...but there's a problem. It doesn't work. It won't actually fail with an error, but it won't change anything either.
That's because authentication sections are locked. To change a setting in a locked section, you need to call Set-WebConfigurationProperty and include the -Location parameter, e.g.,
Set-WebConfigurationProperty `
-filter "/system.webServer/security/authentication/windowsAuthentication" `
-name enabled -value true -PSPath "IIS:\" -location $siteName
I suppose you can still pipe the objects to the foreach-object cmdlet but it's probably going to be a lot easier to read (and maintain) if you script this using a foreach loop.
$siteName = "MySiteName"
$authentications = Get-WebConfiguration `
-filter "system.webServer/security/authentication/*" `
-PSPath "IIS:\Sites\$siteName"
foreach ($auth in $authentications)
{
$auth.SectionPath -match "/windowsAuthentication$"
$enable = ($matches.count -gt 0)
Set-WebConfigurationProperty `
-filter $auth.SectionPath `
-name enabled -value $enable -PSPath "IIS:\" -location $siteName
}

Resources