From a6c9aa986b52165b45ec3fbab9bfe8c91ab7ba6b Mon Sep 17 00:00:00 2001 From: VoidVolker <> Date: Sun, 11 Feb 2024 22:31:53 +0300 Subject: [PATCH] Added config file and net4.8.1 support --- .gitignore | 662 +++++++++--------- LogonService/LogonService.sln | 86 ++- LogonService/LogonService/App.config | 27 +- LogonService/LogonService/AppConfig.cs | 22 + LogonService/LogonService/Args.cs | 230 +++--- LogonService/LogonService/LService.cs | 311 ++++---- ...ice.csproj => LogonServiceNet4.5.1.csproj} | 264 ++++--- LogonService/LogonService/LogonUI.cs | 40 +- LogonService/LogonService/Program.cs | 256 ++++--- .../LogonService/ProjectInstaller.Designer.cs | 122 ++-- LogonService/LogonService/ProjectInstaller.cs | 39 +- .../LogonService/ProjectInstaller.resx | 256 +++---- .../LogonService/Properties/AssemblyInfo.cs | 10 +- .../LogonService/mainForm.Designer.cs | 38 - LogonService/LogonService/mainForm.cs | 20 - LogonService/LogonService/serviceInstaller.cs | 68 +- LogonService/LogonService/util.cs | 97 ++- LogonService/LogonService_4.8.1/App.config | 21 + LogonService/LogonService_4.8.1/AppConfig.cs | 22 + .../LogonService_4.8.1/ApplicationLoader.cs | 212 ++++++ LogonService/LogonService_4.8.1/Args.cs | 115 +++ .../LogonService_4.8.1/LService.Designer.cs | 52 ++ LogonService/LogonService_4.8.1/LService.cs | 188 +++++ LogonService/LogonService_4.8.1/LService.resx | 126 ++++ .../LogonServiceNet4.8.1.csproj | 179 +++++ LogonService/LogonService_4.8.1/LogonUI.cs | 21 + LogonService/LogonService_4.8.1/Program.cs | 150 ++++ .../ProjectInstaller.Designer.cs | 61 ++ .../LogonService_4.8.1/ProjectInstaller.cs | 18 + .../LogonService_4.8.1/ProjectInstaller.resx | 129 ++++ .../Properties/AssemblyInfo.cs | 38 + .../LogonService_4.8.1/serviceInstaller.cs | 35 + LogonService/LogonService_4.8.1/util.cs | 43 ++ README.md | 53 +- 34 files changed, 2815 insertions(+), 1196 deletions(-) create mode 100644 LogonService/LogonService/AppConfig.cs rename LogonService/LogonService/{LogonService.csproj => LogonServiceNet4.5.1.csproj} (50%) delete mode 100644 LogonService/LogonService/mainForm.Designer.cs delete mode 100644 LogonService/LogonService/mainForm.cs create mode 100644 LogonService/LogonService_4.8.1/App.config create mode 100644 LogonService/LogonService_4.8.1/AppConfig.cs create mode 100644 LogonService/LogonService_4.8.1/ApplicationLoader.cs create mode 100644 LogonService/LogonService_4.8.1/Args.cs create mode 100644 LogonService/LogonService_4.8.1/LService.Designer.cs create mode 100644 LogonService/LogonService_4.8.1/LService.cs create mode 100644 LogonService/LogonService_4.8.1/LService.resx create mode 100644 LogonService/LogonService_4.8.1/LogonServiceNet4.8.1.csproj create mode 100644 LogonService/LogonService_4.8.1/LogonUI.cs create mode 100644 LogonService/LogonService_4.8.1/Program.cs create mode 100644 LogonService/LogonService_4.8.1/ProjectInstaller.Designer.cs create mode 100644 LogonService/LogonService_4.8.1/ProjectInstaller.cs create mode 100644 LogonService/LogonService_4.8.1/ProjectInstaller.resx create mode 100644 LogonService/LogonService_4.8.1/Properties/AssemblyInfo.cs create mode 100644 LogonService/LogonService_4.8.1/serviceInstaller.cs create mode 100644 LogonService/LogonService_4.8.1/util.cs diff --git a/.gitignore b/.gitignore index 3e759b7..4ee4030 100644 --- a/.gitignore +++ b/.gitignore @@ -1,330 +1,332 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ -**/Properties/launchSettings.json - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +/dist/*.7z diff --git a/LogonService/LogonService.sln b/LogonService/LogonService.sln index 8881f2f..09673f8 100644 --- a/LogonService/LogonService.sln +++ b/LogonService/LogonService.sln @@ -1,25 +1,61 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.421 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogonService", "LogonService\LogonService.csproj", "{FAC83616-9681-45D0-B15E-407D2059ABCA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {41D7B4FD-3D91-4917-9DB2-12F95CCD167F} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34525.116 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogonServiceNet4.5.1", "LogonService\LogonServiceNet4.5.1.csproj", "{FAC83616-9681-45D0-B15E-407D2059ABCA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogonServiceNet4.8.1", "LogonService_4.8.1\LogonServiceNet4.8.1.csproj", "{FF02D228-C61A-431B-8EFE-78BCAECB7FC3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|Any CPU.Build.0 = Release|Any CPU + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|ARM64.Build.0 = Debug|ARM64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|x64.ActiveCfg = Debug|x64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|x64.Build.0 = Debug|x64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|x86.ActiveCfg = Debug|x86 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Debug|x86.Build.0 = Debug|x86 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|Any CPU.Build.0 = Release|Any CPU + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|ARM64.ActiveCfg = Release|ARM64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|ARM64.Build.0 = Release|ARM64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|x64.ActiveCfg = Release|x64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|x64.Build.0 = Release|x64 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|x86.ActiveCfg = Release|x86 + {FAC83616-9681-45D0-B15E-407D2059ABCA}.Release|x86.Build.0 = Release|x86 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|Any CPU.Build.0 = Release|Any CPU + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|ARM64.Build.0 = Debug|ARM64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|x64.ActiveCfg = Debug|x64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|x64.Build.0 = Debug|x64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|x86.ActiveCfg = Debug|x86 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Debug|x86.Build.0 = Debug|x86 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|Any CPU.Build.0 = Release|Any CPU + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|ARM64.ActiveCfg = Release|ARM64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|ARM64.Build.0 = Release|ARM64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|x64.ActiveCfg = Release|x64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|x64.Build.0 = Release|x64 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|x86.ActiveCfg = Release|x86 + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {41D7B4FD-3D91-4917-9DB2-12F95CCD167F} + EndGlobalSection +EndGlobal diff --git a/LogonService/LogonService/App.config b/LogonService/LogonService/App.config index 9c05822..5b18bb2 100644 --- a/LogonService/LogonService/App.config +++ b/LogonService/LogonService/App.config @@ -1,6 +1,21 @@ - - - - - - \ No newline at end of file + + + + + + + + + + + + + + diff --git a/LogonService/LogonService/AppConfig.cs b/LogonService/LogonService/AppConfig.cs new file mode 100644 index 0000000..060dbfd --- /dev/null +++ b/LogonService/LogonService/AppConfig.cs @@ -0,0 +1,22 @@ +using System; +using System.Configuration; + +namespace LogonService +{ + internal static class AppConfig + { + public static string OnLogon = Get("OnLogon", ""); + public static string LogEnabled = Get("LogEnabled", "false"); + public static string LogPath = Get("LogPath", $"{AppDomain.CurrentDomain.BaseDirectory}log.txt"); + public static string Description = Get("Description", "Logon Service for running applications on logon screen"); + public static string DisplayName = Get("DisplayName", "Logon Service"); + public static string ServiceName = Get("ServiceName", "LogonService"); + + public static string Get(string prop, string defProp = null) + { + var value = ConfigurationManager.AppSettings[prop]; + if (string.IsNullOrEmpty(value)) { value = defProp; } + return value; + } + } +} diff --git a/LogonService/LogonService/Args.cs b/LogonService/LogonService/Args.cs index 7371db4..10eb3e5 100644 --- a/LogonService/LogonService/Args.cs +++ b/LogonService/LogonService/Args.cs @@ -1,115 +1,115 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace LogonService -{ - class Args : Dictionary - { - public char[] prefixes = { '/', '-' }; - public Action msg = (s) => Console.WriteLine(s); - public struct Command - { - public bool isParsed; - public string usage; - public Func, int> action; - public Command(Func, int> a, string u = "") - { - isParsed = false; - action = a; - usage = u; - } - } - - public string Usage() - { - string r = ""; - foreach (KeyValuePair cmd in this) - { - if (prefixes.Length > 0) - { - r += " "; - //r + = prefixes.Join(cmd.Key, " ") - foreach (char c in prefixes) - { - r += c + cmd.Key + " "; - } - r += " —— " + cmd.Value.usage + "\n"; - } - else - { - r += " " + cmd.Key + " —— " + cmd.Value.usage + "\n"; - } - - } - return r; - } - - public void Parse(string[] args) - { - int len = args.Length; - string argument; - //int cmdres = 0; - int i = 0; - while (i < len) - { - //msg("i= " + i + " len= " + len + (i < len).ToString()); - Command cmd; - argument = args[i]; - if (prefixes.Length > 0) - { - if (prefixes.Contains(argument[0])) - { - argument = argument.Substring(1); - if (TryGetValue(argument, out cmd)) - { - if (cmd.isParsed) - { - msg("Argument already parsed: " + argument); - return; - } - else - { - cmd.isParsed = true; - this[argument] = cmd; - i = cmd.action(args, i + 1, msg); - continue; - } - - } - } - } - else - { - if (TryGetValue(argument, out cmd)) - { - if (cmd.isParsed) - { - msg("Argument already parsed: " + argument); - return; - } - else - { - cmd.isParsed = true; - this[argument] = cmd; - i = cmd.action(args, i + 1, msg); - continue; - } - } - } - msg(" Unknown argument: " + argument + "\n" + Usage()); - return; - } - } - - public Args() - { - Add("h", new Command((string[] a, int next, Action m) => - { - m(Usage()); - return next; - }, " Show all commands help") - ); - } - } -} +//using System; +//using System.Collections.Generic; +//using System.Linq; + +//namespace LogonService +//{ +// class Args : Dictionary +// { +// public char[] prefixes = { '/', '-' }; +// public Action msg = (s) => Console.WriteLine(s); +// public struct Command +// { +// public bool isParsed; +// public string usage; +// public Func, int> action; +// public Command(Func, int> a, string u = "") +// { +// isParsed = false; +// action = a; +// usage = u; +// } +// } + +// public string Usage() +// { +// string r = ""; +// foreach (KeyValuePair cmd in this) +// { +// if (prefixes.Length > 0) +// { +// r += " "; +// //r + = prefixes.Join(cmd.Key, " ") +// foreach (char c in prefixes) +// { +// r += c + cmd.Key + " "; +// } +// r += " —— " + cmd.Value.usage + "\n"; +// } +// else +// { +// r += " " + cmd.Key + " —— " + cmd.Value.usage + "\n"; +// } + +// } +// return r; +// } + +// public void Parse(string[] args) +// { +// int len = args.Length; +// string argument; +// //int cmdres = 0; +// int i = 0; +// while (i < len) +// { +// //msg("i= " + i + " len= " + len + (i < len).ToString()); +// Command cmd; +// argument = args[i]; +// if (prefixes.Length > 0) +// { +// if (prefixes.Contains(argument[0])) +// { +// argument = argument.Substring(1); +// if (TryGetValue(argument, out cmd)) +// { +// if (cmd.isParsed) +// { +// msg("Argument already parsed: " + argument); +// return; +// } +// else +// { +// cmd.isParsed = true; +// this[argument] = cmd; +// i = cmd.action(args, i + 1, msg); +// continue; +// } + +// } +// } +// } +// else +// { +// if (TryGetValue(argument, out cmd)) +// { +// if (cmd.isParsed) +// { +// msg("Argument already parsed: " + argument); +// return; +// } +// else +// { +// cmd.isParsed = true; +// this[argument] = cmd; +// i = cmd.action(args, i + 1, msg); +// continue; +// } +// } +// } +// msg(" Unknown argument: " + argument + "\n" + Usage()); +// return; +// } +// } + +// public Args() +// { +// Add("h", new Command((string[] a, int next, Action m) => +// { +// m(Usage()); +// return next; +// }, " Show all commands help") +// ); +// } +// } +//} diff --git a/LogonService/LogonService/LService.cs b/LogonService/LogonService/LService.cs index 8621f37..5386736 100644 --- a/LogonService/LogonService/LService.cs +++ b/LogonService/LogonService/LService.cs @@ -1,123 +1,188 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; -using System.Linq; -using System.ServiceProcess; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -//using System.Windows.Forms; - -namespace LogonService -{ - public partial class LService : ServiceBase - { - ApplicationLoader.PROCESS_INFORMATION procInfo; - //mainForm mForm; - static bool isConsole = false; - private readonly Thread appThread; - private bool isActive = true; - public static string logonApp = "LogonUI"; - public static string logonAppExe = logonApp + ".exe"; - public static string logonAppPath; - Process helperProc = null; - - //public bool CanShutdown = true; - //public bool CanStop = true; - - public LService(bool isCon) - { - isConsole = isCon; - InitializeComponent(); - appThread = new Thread(App); - appThread.SetApartmentState(ApartmentState.STA); - } - - void App() - { - logonAppPath = AppDomain.CurrentDomain.BaseDirectory + logonAppExe; - - - while (isActive) - { - helperProc = Util.TryProc(logonApp); - - if (LogonUI.IsLogonMode()) - { - if (helperProc == null) - { - ApplicationLoader.StartProcessAndBypassUAC(logonAppPath, out procInfo); - - } - else if (ApplicationLoader.IsNewSession()) - { - try - { - helperProc.Kill(); - } - catch (Exception) - { - } - ApplicationLoader.StartProcessAndBypassUAC(logonAppPath, out procInfo); - } - } - else - { - if (helperProc != null) - { - try - { - helperProc.Kill(); - } - catch (Exception) - { - } - } - } - helperProc = null; - Thread.Sleep(100); - } - } - - public void Start() - { - appThread.Start(); - } - - public void HStop() - { - isActive = false; - if (helperProc != null) - { - try - { - helperProc.Kill(); - } - catch (Exception) - { - } - helperProc = null; - } - } - - protected override void OnStart(string[] args) - { - Start(); - } - - protected override void OnStop() - { - Stop(); - } - - protected override void OnShutdown() - { - // Add your save code here - Stop(); - base.OnShutdown(); - } - } -} +using System; +using System.IO; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.ServiceProcess; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Configuration; +//using System.Windows.Forms; + +namespace LogonService +{ + public partial class LService : ServiceBase + { + private const int WatchInterval = 100; // ms + + ApplicationLoader.PROCESS_INFORMATION procInfo; + //mainForm mForm; + static bool isConsole = false; + private readonly Thread appThread; + private bool isActive = true; + private string logPath; + private bool isLogging = false; + + public string execApp; + public string execAppPath; + + Process executingProc = null; + //readonly Command cmd = Command.Execute; + + //public bool CanShutdown = true; + //public bool CanStop = true; + + public LService(bool isCon) + { + isConsole = isCon; + InitializeComponent(); + + //Get log path + logPath = AppConfig.LogPath; + // Turning log on or off + isLogging = bool.Parse(AppConfig.LogEnabled); + + //var command = AppConfig.OnLogon; + //switch (command) + //{ + // default: + // cmd = Command.Execute; + // execAppPath = command; + // execApp = Path.GetFileNameWithoutExtension(execAppPath); + // appThread = new Thread(Execute_Proc); + // break; + //} + + // Configuring app to run + + execAppPath = AppConfig.OnLogon; + execApp = Path.GetFileNameWithoutExtension(execAppPath); + appThread = new Thread(Execute_Proc); + + appThread.SetApartmentState(ApartmentState.STA); + } + + void Log(string str) + { + if (isLogging) + { + File.AppendAllText(logPath, $"[{DateTime.Now}] {str}\n"); + } + } + + void Execute_Proc() + { + while (isActive) + { + executingProc = Util.TryProc(execApp); + + if (LogonUI.IsLogonMode()) + { + if (executingProc == null) + { + Log($"Logon mode detected - application not running: starting application"); + ApplicationLoader.StartProcessAndBypassUAC(execAppPath, out procInfo); + } + else if (ApplicationLoader.IsNewSession()) + { + Log($"Logon mode detected - application is running: new session detected"); + + try + { + Log($"Killing application"); + executingProc.Kill(); + } + catch (Exception e) + { + Log(e.Message); + Log(e.StackTrace); + } + Log($"Application killed: starting application from scratch"); + ApplicationLoader.StartProcessAndBypassUAC(execAppPath, out procInfo); + } + } + else + { + if (executingProc != null) + { + Log($"User logged in detected: killing application"); + try + { + executingProc.Kill(); + } + catch (Exception e) + { + Log(e.Message); + Log(e.StackTrace); + } + } + } + executingProc = null; + Thread.Sleep(WatchInterval); + } + } + + public void Start() + { + if (string.IsNullOrEmpty(execAppPath)) + { + Log($"Service is started. No comand found to execute in App.config - main thread will not start."); + } + else + { + Log($"Service is started. Founded comand from settings: '{execAppPath}'"); + //Log($"Service is started. Founded comand from settings: {cmd}"); + appThread.Start(); + } + } + + public void LogonWatcherStop() + { + isActive = false; + if (executingProc != null) + { + try + { + executingProc.Kill(); + } + catch (Exception) + { + } + executingProc = null; + } + } + + protected override void OnStart(string[] args) + { + Start(); + base.OnStart(args); + } + + protected override void OnStop() + { + //Log($"OnStop()"); + LogonWatcherStop(); + //Stop(); + base.OnStop(); + } + + protected override void OnShutdown() + { + //Log($"OnShutdown()"); + // Add your save code here + LogonWatcherStop(); + Stop(); + base.OnShutdown(); + } + + //enum Command : byte + //{ + // None, + // Execute, + // LogonUI_WindowHide + //} + } +} diff --git a/LogonService/LogonService/LogonService.csproj b/LogonService/LogonService/LogonServiceNet4.5.1.csproj similarity index 50% rename from LogonService/LogonService/LogonService.csproj rename to LogonService/LogonService/LogonServiceNet4.5.1.csproj index 71aff6f..4f41fd3 100644 --- a/LogonService/LogonService/LogonService.csproj +++ b/LogonService/LogonService/LogonServiceNet4.5.1.csproj @@ -1,100 +1,178 @@ - - - - - Debug - AnyCPU - {FAC83616-9681-45D0-B15E-407D2059ABCA} - Exe - Properties - LogonService - LogonService - v4.5.1 - 512 - true - 1.0.0.3 - - - x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - Component - - - LService.cs - - - - - - Form - - - mainForm.cs - - - - Component - - - ProjectInstaller.cs - - - - - - - - - - - LService.cs - - - ProjectInstaller.cs - - - + + + + + Debug + AnyCPU + {FAC83616-9681-45D0-B15E-407D2059ABCA} + Exe + Properties + LogonService + LogonService + v4.5.1 + 512 + true + 1.1.0.67 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + none + true + bin\Release\ + TRACE + prompt + 4 + + + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + true + + + bin\x86\Release\ + TRACE + true + none + x86 + 7.3 + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + true + + + bin\x64\Release\ + TRACE + true + none + x64 + 7.3 + prompt + true + + + true + bin\ARM64\Debug\ + DEBUG;TRACE + full + ARM64 + 7.3 + prompt + true + + + bin\ARM64\Release\ + TRACE + true + none + ARM64 + 7.3 + prompt + true + + + + + + + + + + + + + + + + + + + + + Component + + + LService.cs + + + + + + + Component + + + ProjectInstaller.cs + + + + + + + + + + + LService.cs + + + ProjectInstaller.cs + + + + + False + .NET Framework 3.5 SP1 + false + + + + --> \ No newline at end of file diff --git a/LogonService/LogonService/LogonUI.cs b/LogonService/LogonService/LogonUI.cs index 3edd3f6..a03483c 100644 --- a/LogonService/LogonService/LogonUI.cs +++ b/LogonService/LogonService/LogonUI.cs @@ -1,19 +1,21 @@ -using System.Runtime.InteropServices; - -namespace LogonService -{ - static class LogonUI - { - [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] - static extern int GetSystemMetrics(int nIndex); - const int SM_SHUTTINGDOWN = 0x2000; - - static readonly string LogonUIexe = "LogonUI.exe"; - static readonly string logonPath = @"C:\Windows\System32\" + LogonUIexe; - - public static bool IsLogonMode() - { - return (GetSystemMetrics(SM_SHUTTINGDOWN) == 0) & Util.IsProcExist("LogonUI"); - } - } -} +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace LogonService +{ + static class LogonUI + { + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + static extern int GetSystemMetrics(int nIndex); + const int SM_SHUTTINGDOWN = 0x2000; + + const string LogonUIName = "LogonUI"; + const string LogonUIexe = LogonUIName + ".exe"; + const string logonPath = @"C:\Windows\System32\" + LogonUIexe; + + public static bool IsLogonMode() + { + return (GetSystemMetrics(SM_SHUTTINGDOWN) == 0) & Util.IsProcExist(LogonUIName); + } + } +} diff --git a/LogonService/LogonService/Program.cs b/LogonService/LogonService/Program.cs index 95e71f7..50ab859 100644 --- a/LogonService/LogonService/Program.cs +++ b/LogonService/LogonService/Program.cs @@ -1,106 +1,150 @@ -using System; -using System.IO; -using System.ServiceProcess; -using System.Diagnostics; - -namespace LogonService -{ - static class Program - { - /// - /// Главная точка входа для приложения. - /// - static void Main(string[] args) - { - //ServiceBase[] ServicesToRun; - //ServicesToRun = new ServiceBase[] - //{ - // new adsrpService() - //}; - //ServiceBase.Run(ServicesToRun); - if (args != null && args.Length == 1 && args[0].Length > 1 - && (args[0][0] == '-' || args[0][0] == '/')) - { - switch (args[0].Substring(1).ToLower()) - { - case "install": - case "i": - if (ServiceInstaller.Install()) - { - Console.WriteLine("Service installed"); - Process.Start("net", "start logonService"); - } - else - { - Console.WriteLine("Failed to install service"); - } - - break; - case "uninstall": - case "u": - if (ServiceInstaller.Uninstall()) - { - Console.WriteLine("Service uninstalled"); - } - else - { - Console.WriteLine("Failed to uninstall service"); - } - - break; - default: - Console.WriteLine("Unrecognized parameters.\n\n -i /i -install /install — install service\n\n -u /u -uninstall /uninstall — uninstall service"); - break; - } - } - else - { - try - { - //bool isConsole = Environment.UserInteractive; - LService service = new LService(false); - ServiceBase[] servicesToRun = new ServiceBase[] { service }; - - //if (isConsole) - //{ - // Console.OutputEncoding = Encoding.UTF8; - // Console.CancelKeyPress += (x, y) => service.Stop(); - // try - // { - // service.start(); - // } - // catch - // { - // Console.WriteLine("Initialization unknown error"); - // throw; - // } - - // Console.WriteLine("Service started. Press any key to stop."); - // Console.ReadKey(); - // service.stop(); - // Console.WriteLine("Service stopped. Good bye."); - //} - //else - //{ - ServiceBase.Run(servicesToRun); - //} - } - catch (IOException ex) - { - //log.Error("", ex); - Console.WriteLine("IOException", ex); - } - catch (Exception ex) - { - //log.Fatal("Could not start polling service due to unknown error", ex); - Console.WriteLine("Could not start service due application error", ex); - } - //catch - //{ - // //log.Fatal("Could not start polling service due to unknown error", ex); - // Console.WriteLine("Could not start service due to unknown error"); - //} - } - } - } -} +using System; +using System.IO; +using System.ServiceProcess; +using System.Diagnostics; + +namespace LogonService +{ + static class Program + { + /// + /// Главная точка входа для приложения. + /// + static void Main(string[] args) + { + //ServiceBase[] ServicesToRun; + //ServicesToRun = new ServiceBase[] + //{ + // new adsrpService() + //}; + //ServiceBase.Run(ServicesToRun); + if (args != null && args.Length == 1 && args[0].Length > 1 + && (args[0][0] == '-' || args[0][0] == '/')) + { + var serviceName = AppConfig.ServiceName; + + switch (args[0].Substring(1).ToLower()) + { + case "install": + case "i": + try + { + ServiceInstaller.Install(); + Process.Start("net", $"start {serviceName}"); + Console.WriteLine("Service installed and started"); + } + catch (Exception e) + { + Console.WriteLine("Failed to install service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + case "uninstall": + case "u": + try + { + Process.Start("net", $"stop {serviceName}"); + ServiceInstaller.Uninstall(); + Console.WriteLine("Service stopped and uninstalled"); + } + catch (Exception e) + { + Console.WriteLine("Failed to uninstall service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + case "reinstall": + case "r": + try + { + Process.Start("net", $"stop {serviceName}"); + ServiceInstaller.Uninstall(); + ServiceInstaller.Install(); + Process.Start("net", $"start {serviceName}"); + Console.WriteLine("Service stopped and uninstalled"); + } + catch (Exception e) + { + Console.WriteLine("Failed to uninstall service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + + case "start": + Process.Start("net", $"start {serviceName}"); + break; + + case "stop": + Process.Start("net", $"stop {serviceName}"); + break; + + default: + Console.WriteLine("Unrecognized parameters.\n\n" + + " -i /i -install /install — install and start service\n\n" + + " -u /u -uninstall /uninstall — stop and uninstall service\n\n" + + " -r /r -reinstall /reinstall — reinstall service\n\n" + + " -start /start — start service\n\n" + + " -stop /stop — stop service\n\n" + ); + break; + } + } + else + { + try + { + //bool isConsole = Environment.UserInteractive; + LService service = new LService(false); + ServiceBase[] servicesToRun = new ServiceBase[] { service }; + + //if (isConsole) + //{ + // Console.OutputEncoding = Encoding.UTF8; + // Console.CancelKeyPress += (x, y) => service.Stop(); + // try + // { + // service.start(); + // } + // catch + // { + // Console.WriteLine("Initialization unknown error"); + // throw; + // } + + // Console.WriteLine("Service started. Press any key to stop."); + // Console.ReadKey(); + // service.stop(); + // Console.WriteLine("Service stopped. Good bye."); + //} + //else + //{ + ServiceBase.Run(servicesToRun); + //} + } + catch (IOException ex) + { + //log.Error("", ex); + Console.WriteLine("IOException", ex); + } + catch (Exception ex) + { + //log.Fatal("Could not start polling service due to unknown error", ex); + Console.WriteLine("Could not start service due application error", ex); + } + //catch + //{ + // //log.Fatal("Could not start polling service due to unknown error", ex); + // Console.WriteLine("Could not start service due to unknown error"); + //} + } + } + + + } +} diff --git a/LogonService/LogonService/ProjectInstaller.Designer.cs b/LogonService/LogonService/ProjectInstaller.Designer.cs index ac2392f..4a8c3e7 100644 --- a/LogonService/LogonService/ProjectInstaller.Designer.cs +++ b/LogonService/LogonService/ProjectInstaller.Designer.cs @@ -1,61 +1,61 @@ -namespace LogonService -{ - partial class ProjectInstaller - { - /// - /// Требуется переменная конструктора. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Освободить все используемые ресурсы. - /// - /// истинно, если управляемый ресурс должен быть удален; иначе ложно. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Код, автоматически созданный конструктором компонентов - - /// - /// Обязательный метод для поддержки конструктора - не изменяйте - /// содержимое данного метода при помощи редактора кода. - /// - private void InitializeComponent() - { - this.adsprServiceInstaller = new System.ServiceProcess.ServiceProcessInstaller(); - this.adsprInstaller = new System.ServiceProcess.ServiceInstaller(); - // - // adsprServiceInstaller - // - this.adsprServiceInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem; - this.adsprServiceInstaller.Password = "adspr"; - this.adsprServiceInstaller.Username = "adspr"; - // - // adsprInstaller - // - this.adsprInstaller.Description = "AD Self Password Reset Helper Logon Service"; - this.adsprInstaller.DisplayName = "ADSPR Logon Service"; - this.adsprInstaller.ServiceName = "logonService"; - this.adsprInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; - // - // ProjectInstaller - // - this.Installers.AddRange(new System.Configuration.Install.Installer[] { - this.adsprServiceInstaller, - this.adsprInstaller}); - - } - - #endregion - - private System.ServiceProcess.ServiceProcessInstaller adsprServiceInstaller; - private System.ServiceProcess.ServiceInstaller adsprInstaller; - - } -} \ No newline at end of file +namespace LogonService +{ + partial class ProjectInstaller + { + /// + /// Требуется переменная конструктора. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Освободить все используемые ресурсы. + /// + /// истинно, если управляемый ресурс должен быть удален; иначе ложно. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором компонентов + + /// + /// Обязательный метод для поддержки конструктора - не изменяйте + /// содержимое данного метода при помощи редактора кода. + /// + private void InitializeComponent() + { + this.adsprServiceInstaller = new System.ServiceProcess.ServiceProcessInstaller(); + this.LogonServiceInstaller = new System.ServiceProcess.ServiceInstaller(); + // + // adsprServiceInstaller + // + this.adsprServiceInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem; + this.adsprServiceInstaller.Password = "lsrv"; + this.adsprServiceInstaller.Username = "lsrv"; + // + // LogonServiceInstaller + // + this.LogonServiceInstaller.Description = "Logon Service for running applications on logon screen"; + this.LogonServiceInstaller.DisplayName = "Logon Service"; + this.LogonServiceInstaller.ServiceName = "LogonService"; + this.LogonServiceInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; + // + // ProjectInstaller + // + this.Installers.AddRange(new System.Configuration.Install.Installer[] { + this.adsprServiceInstaller, + this.LogonServiceInstaller}); + + } + + #endregion + + private System.ServiceProcess.ServiceProcessInstaller adsprServiceInstaller; + private System.ServiceProcess.ServiceInstaller LogonServiceInstaller; + + } +} diff --git a/LogonService/LogonService/ProjectInstaller.cs b/LogonService/LogonService/ProjectInstaller.cs index 1417957..f97643a 100644 --- a/LogonService/LogonService/ProjectInstaller.cs +++ b/LogonService/LogonService/ProjectInstaller.cs @@ -1,21 +1,18 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Configuration.Install; -using System.Linq; -using System.Threading.Tasks; - -namespace LogonService -{ - [RunInstaller(true)] - public partial class ProjectInstaller : System.Configuration.Install.Installer - { - public ProjectInstaller() - { - InitializeComponent(); - } - - - } -} +using System.ComponentModel; +using System.Configuration; + +namespace LogonService +{ + [RunInstaller(true)] + public partial class ProjectInstaller : System.Configuration.Install.Installer + { + public ProjectInstaller() + { + InitializeComponent(); + + LogonServiceInstaller.Description = AppConfig.Description; + LogonServiceInstaller.DisplayName = AppConfig.DisplayName; + LogonServiceInstaller.ServiceName = AppConfig.ServiceName; + } + } +} diff --git a/LogonService/LogonService/ProjectInstaller.resx b/LogonService/LogonService/ProjectInstaller.resx index 544645d..e7b532b 100644 --- a/LogonService/LogonService/ProjectInstaller.resx +++ b/LogonService/LogonService/ProjectInstaller.resx @@ -1,129 +1,129 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 56 - - - 186, 22 - - - False - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 63 + + + 186, 22 + + + False + \ No newline at end of file diff --git a/LogonService/LogonService/Properties/AssemblyInfo.cs b/LogonService/LogonService/Properties/AssemblyInfo.cs index 51a0624..7e84100 100644 --- a/LogonService/LogonService/Properties/AssemblyInfo.cs +++ b/LogonService/LogonService/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("VoidVolker")] [assembly: AssemblyProduct("Logon service")] -[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,7 @@ // Можно задать все значения или принять номера сборки и редакции по умолчанию // используя "*", как показано ниже: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.3")] -[assembly: AssemblyFileVersion("1.0.0.3")] +[assembly: AssemblyVersion("1.1.0.67")] +[assembly: AssemblyFileVersion("1.1.0.67")] + +[assembly: AssemblyInformationalVersion("0.0.0.63")] \ No newline at end of file diff --git a/LogonService/LogonService/mainForm.Designer.cs b/LogonService/LogonService/mainForm.Designer.cs deleted file mode 100644 index cd2c6a6..0000000 --- a/LogonService/LogonService/mainForm.Designer.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace LogonService -{ - partial class mainForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Text = "mainForm"; - } - - #endregion - } -} \ No newline at end of file diff --git a/LogonService/LogonService/mainForm.cs b/LogonService/LogonService/mainForm.cs deleted file mode 100644 index f77e3e4..0000000 --- a/LogonService/LogonService/mainForm.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace LogonService -{ - public partial class mainForm : Form - { - public mainForm() - { - InitializeComponent(); - } - } -} diff --git a/LogonService/LogonService/serviceInstaller.cs b/LogonService/LogonService/serviceInstaller.cs index 659bd4f..913a8a9 100644 --- a/LogonService/LogonService/serviceInstaller.cs +++ b/LogonService/LogonService/serviceInstaller.cs @@ -1,33 +1,35 @@ -using System.Configuration.Install; -using System.Reflection; - -namespace LogonService -{ - class ServiceInstaller - { - //private static readonly ILog log = LogManager.GetLogger(typeof(Program)); - private static readonly string exePath = Assembly.GetExecutingAssembly().Location; - - public static bool Install() - { - try { ManagedInstallerClass.InstallHelper(new[] { exePath }); } - catch { return false; } - return true; - } - - public static bool Uninstall() - { - //if( EventLog.Exists(adsrpService.evLogSource) ) - //{ - // EventLog.Delete(adsrpService.evLogSource); - //} - //if (EventLog.SourceExists(adsrpService.evLogSource)) - //{ - // EventLog.DeleteEventSource(adsrpService.evLogSource); - //} - try { ManagedInstallerClass.InstallHelper(new[] { "/u", exePath }); } - catch { return false; } - return true; - } - } -} +using System.Configuration.Install; +using System.Reflection; + +namespace LogonService +{ + class ServiceInstaller + { + //private static readonly ILog log = LogManager.GetLogger(typeof(Program)); + private static readonly string exePath = Assembly.GetExecutingAssembly().Location; + + public static void Install() + { + ManagedInstallerClass.InstallHelper(new[] { exePath }); + //try { ManagedInstallerClass.InstallHelper(new[] { exePath }); } + //catch { return false; } + //return true; + } + + public static void Uninstall() + { + ManagedInstallerClass.InstallHelper(new[] { "/u", exePath }); + //if( EventLog.Exists(adsrpService.evLogSource) ) + //{ + // EventLog.Delete(adsrpService.evLogSource); + //} + //if (EventLog.SourceExists(adsrpService.evLogSource)) + //{ + // EventLog.DeleteEventSource(adsrpService.evLogSource); + //} + //try { ManagedInstallerClass.InstallHelper(new[] { "/u", exePath }); } + //catch { return false; } + //return true; + } + } +} diff --git a/LogonService/LogonService/util.cs b/LogonService/LogonService/util.cs index 787e6c6..d93a136 100644 --- a/LogonService/LogonService/util.cs +++ b/LogonService/LogonService/util.cs @@ -1,54 +1,43 @@ -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace LogonService -{ - static class Util - { - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool IsWindowVisible(IntPtr hWnd); - - public static bool IsProcExist(string name) - { - Process[] arrProcesses = Process.GetProcessesByName(name); - return arrProcesses.Length > 0; - } - - public static Process TryProc(string name) - { - Process[] arrProcesses = Process.GetProcessesByName(name); - if (arrProcesses.Length > 0) - { - return arrProcesses[0]; - } - else - { - return null; - } - } - - public static bool IsProcWinVisible(Process proc) - { - return IsWindowVisible(proc.MainWindowHandle); - } - - public static bool IsProcWinVisible(string name) - { - Process[] arrProcesses = Process.GetProcessesByName(name); - bool r = false; - if (arrProcesses.Length > 0) - { - for (var i = 0; i < arrProcesses.Length; i++) - { - if (!r) - { - r = IsWindowVisible(arrProcesses[i].MainWindowHandle); - } - } - } - return r; - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; + +namespace LogonService +{ + static class Util + { + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindowVisible(IntPtr hWnd); + + + private const int SW_HIDE = 0; + private const int SW_SHOW = 5; + [DllImport("User32")] + private static extern int ShowWindow(IntPtr hwnd, int nCmdShow); + + public static bool IsProcExist(string name) + { + Process[] arrProcesses = Process.GetProcessesByName(name); + return arrProcesses.Length > 0; + } + + public static Process TryProc(string name) + { + Process[] arrProcesses = Process.GetProcessesByName(name); + if (arrProcesses.Length > 0) + { + return arrProcesses[0]; + } + else + { + return null; + } + } + } +} diff --git a/LogonService/LogonService_4.8.1/App.config b/LogonService/LogonService_4.8.1/App.config new file mode 100644 index 0000000..18e114d --- /dev/null +++ b/LogonService/LogonService_4.8.1/App.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/LogonService/LogonService_4.8.1/AppConfig.cs b/LogonService/LogonService_4.8.1/AppConfig.cs new file mode 100644 index 0000000..060dbfd --- /dev/null +++ b/LogonService/LogonService_4.8.1/AppConfig.cs @@ -0,0 +1,22 @@ +using System; +using System.Configuration; + +namespace LogonService +{ + internal static class AppConfig + { + public static string OnLogon = Get("OnLogon", ""); + public static string LogEnabled = Get("LogEnabled", "false"); + public static string LogPath = Get("LogPath", $"{AppDomain.CurrentDomain.BaseDirectory}log.txt"); + public static string Description = Get("Description", "Logon Service for running applications on logon screen"); + public static string DisplayName = Get("DisplayName", "Logon Service"); + public static string ServiceName = Get("ServiceName", "LogonService"); + + public static string Get(string prop, string defProp = null) + { + var value = ConfigurationManager.AppSettings[prop]; + if (string.IsNullOrEmpty(value)) { value = defProp; } + return value; + } + } +} diff --git a/LogonService/LogonService_4.8.1/ApplicationLoader.cs b/LogonService/LogonService_4.8.1/ApplicationLoader.cs new file mode 100644 index 0000000..8a78783 --- /dev/null +++ b/LogonService/LogonService_4.8.1/ApplicationLoader.cs @@ -0,0 +1,212 @@ +using System; +using System.Security; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace LogonService +{ + class ApplicationLoader + { + #region Structures + + [StructLayout(LayoutKind.Sequential)] + public struct SECURITY_ATTRIBUTES + { + public int Length; + public IntPtr lpSecurityDescriptor; + public bool bInheritHandle; + } + + [StructLayout(LayoutKind.Sequential)] + public struct STARTUPINFO + { + public int cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public uint dwX; + public uint dwY; + public uint dwXSize; + public uint dwYSize; + public uint dwXCountChars; + public uint dwYCountChars; + public uint dwFillAttribute; + public uint dwFlags; + public short wShowWindow; + public short cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public uint dwProcessId; + public uint dwThreadId; + } + + #endregion + + #region Enumerations + + enum TOKEN_TYPE : int + { + TokenPrimary = 1, + TokenImpersonation = 2 + } + + enum SECURITY_IMPERSONATION_LEVEL : int + { + SecurityAnonymous = 0, + SecurityIdentification = 1, + SecurityImpersonation = 2, + SecurityDelegation = 3, + } + + #endregion + + #region Constants + + public const int TOKEN_DUPLICATE = 0x0002; + public const uint MAXIMUM_ALLOWED = 0x2000000; + public const int CREATE_NEW_CONSOLE = 0x00000010; + + public const int IDLE_PRIORITY_CLASS = 0x40; + public const int NORMAL_PRIORITY_CLASS = 0x20; + public const int HIGH_PRIORITY_CLASS = 0x80; + public const int REALTIME_PRIORITY_CLASS = 0x100; + + #endregion + + #region Win32 API Imports + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool CloseHandle(IntPtr hSnapshot); + + [DllImport("kernel32.dll")] + static extern uint WTSGetActiveConsoleSessionId(); + + [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, + ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, + String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); + + [DllImport("kernel32.dll")] + static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId); + + [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")] + public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, + ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, + int ImpersonationLevel, ref IntPtr DuplicateTokenHandle); + + [DllImport("kernel32.dll")] + static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId); + + [DllImport("advapi32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] + static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle); + + //[DllImport("advapi32.dll", SetLastError = true)] + //static extern Boolean SetTokenInformation(ref IntPtr TokenHandle, int TokenInformationClass, + // ref UInt32 TokenInformation, UInt32 TokenInformationLength); + + #endregion + + public static uint lastSession = 0; + public static bool IsNewSession() + { + return lastSession != WTSGetActiveConsoleSessionId(); + } + + /// + /// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt + /// + /// The name of the application to launch + /// Process information regarding the launched application that gets returned to the caller + /// + public static bool StartProcessAndBypassUAC(String applicationName, out PROCESS_INFORMATION procInfo) + { + uint winlogonPid = 0; + IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero; + procInfo = new PROCESS_INFORMATION(); + + // obtain the currently active session id; every logged on user in the system has a unique session id + lastSession = WTSGetActiveConsoleSessionId(); + + // obtain the process id of the winlogon process that is running within the currently active session + //Process[] processes = Process.GetProcessesByName("winlogon"); + Process[] processes = Process.GetProcessesByName("LogonUI"); + foreach (Process p in processes) + { + if ((uint)p.SessionId == lastSession) + { + winlogonPid = (uint)p.Id; + } + } + + // obtain a handle to the winlogon process + hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid); + //hProcess = OpenProcess(MAXIMUM_ALLOWED, false, (uint)Process.GetCurrentProcess().Id); + + // obtain a handle to the access token of the winlogon process + if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken)) + { + CloseHandle(hProcess); + return false; + } + //int ttt = 1; + //SetTokenInformation(ref hPToken, 12, ref ttt, 4); + // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser + // I would prefer to not have to use a security attribute variable and to just + // simply pass null and inherit (by default) the security attributes + // of the existing token. However, in C# structures are value types and therefore + // cannot be assigned the null value. + SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); + sa.Length = Marshal.SizeOf(sa); + + // copy the access token of the winlogon process; the newly created token will be a primary token + if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup)) + { + CloseHandle(hProcess); + CloseHandle(hPToken); + return false; + } + + // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning + // the window station has a desktop that is invisible and the process is incapable of receiving + // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user + // interaction with the new process. + STARTUPINFO si = new STARTUPINFO(); + si.cb = (int)Marshal.SizeOf(si); + //si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop + si.lpDesktop = @"WinSta0\Winlogon"; + // flags that specify the priority and creation method of the process + //int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; + int dwCreationFlags = NORMAL_PRIORITY_CLASS; + + // create a new process in the current user's logon session + bool result = CreateProcessAsUser(hUserTokenDup, // client's access token + null, // file to execute + applicationName, // command line + ref sa, // pointer to process SECURITY_ATTRIBUTES + ref sa, // pointer to thread SECURITY_ATTRIBUTES + false, // handles are not inheritable + dwCreationFlags, // creation flags + IntPtr.Zero, // pointer to new environment block + null, // name of current directory + ref si, // pointer to STARTUPINFO structure + out procInfo // receives information about new process + ); + + // invalidate the handles + CloseHandle(hProcess); + CloseHandle(hPToken); + CloseHandle(hUserTokenDup); + + return result; // return the result + } + } +} diff --git a/LogonService/LogonService_4.8.1/Args.cs b/LogonService/LogonService_4.8.1/Args.cs new file mode 100644 index 0000000..10eb3e5 --- /dev/null +++ b/LogonService/LogonService_4.8.1/Args.cs @@ -0,0 +1,115 @@ +//using System; +//using System.Collections.Generic; +//using System.Linq; + +//namespace LogonService +//{ +// class Args : Dictionary +// { +// public char[] prefixes = { '/', '-' }; +// public Action msg = (s) => Console.WriteLine(s); +// public struct Command +// { +// public bool isParsed; +// public string usage; +// public Func, int> action; +// public Command(Func, int> a, string u = "") +// { +// isParsed = false; +// action = a; +// usage = u; +// } +// } + +// public string Usage() +// { +// string r = ""; +// foreach (KeyValuePair cmd in this) +// { +// if (prefixes.Length > 0) +// { +// r += " "; +// //r + = prefixes.Join(cmd.Key, " ") +// foreach (char c in prefixes) +// { +// r += c + cmd.Key + " "; +// } +// r += " —— " + cmd.Value.usage + "\n"; +// } +// else +// { +// r += " " + cmd.Key + " —— " + cmd.Value.usage + "\n"; +// } + +// } +// return r; +// } + +// public void Parse(string[] args) +// { +// int len = args.Length; +// string argument; +// //int cmdres = 0; +// int i = 0; +// while (i < len) +// { +// //msg("i= " + i + " len= " + len + (i < len).ToString()); +// Command cmd; +// argument = args[i]; +// if (prefixes.Length > 0) +// { +// if (prefixes.Contains(argument[0])) +// { +// argument = argument.Substring(1); +// if (TryGetValue(argument, out cmd)) +// { +// if (cmd.isParsed) +// { +// msg("Argument already parsed: " + argument); +// return; +// } +// else +// { +// cmd.isParsed = true; +// this[argument] = cmd; +// i = cmd.action(args, i + 1, msg); +// continue; +// } + +// } +// } +// } +// else +// { +// if (TryGetValue(argument, out cmd)) +// { +// if (cmd.isParsed) +// { +// msg("Argument already parsed: " + argument); +// return; +// } +// else +// { +// cmd.isParsed = true; +// this[argument] = cmd; +// i = cmd.action(args, i + 1, msg); +// continue; +// } +// } +// } +// msg(" Unknown argument: " + argument + "\n" + Usage()); +// return; +// } +// } + +// public Args() +// { +// Add("h", new Command((string[] a, int next, Action m) => +// { +// m(Usage()); +// return next; +// }, " Show all commands help") +// ); +// } +// } +//} diff --git a/LogonService/LogonService_4.8.1/LService.Designer.cs b/LogonService/LogonService_4.8.1/LService.Designer.cs new file mode 100644 index 0000000..2c3ffd4 --- /dev/null +++ b/LogonService/LogonService_4.8.1/LService.Designer.cs @@ -0,0 +1,52 @@ +namespace LogonService +{ + partial class LService + { + /// + /// Требуется переменная конструктора. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Освободить все используемые ресурсы. + /// + /// истинно, если управляемый ресурс должен быть удален; иначе ложно. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором компонентов + + /// + /// Обязательный метод для поддержки конструктора - не изменяйте + /// содержимое данного метода при помощи редактора кода. + /// + private void InitializeComponent() + { + this.eventLog = new System.Diagnostics.EventLog(); + ((System.ComponentModel.ISupportInitialize)(this.eventLog)).BeginInit(); + // + // eventLog + // + this.eventLog.Log = "Application"; + this.eventLog.Source = "ADSPR"; + // + // adsrpService + // + this.CanShutdown = true; + this.ServiceName = "ADSPR"; + ((System.ComponentModel.ISupportInitialize)(this.eventLog)).EndInit(); + + } + + #endregion + + public System.Diagnostics.EventLog eventLog; + + } +} diff --git a/LogonService/LogonService_4.8.1/LService.cs b/LogonService/LogonService_4.8.1/LService.cs new file mode 100644 index 0000000..5386736 --- /dev/null +++ b/LogonService/LogonService_4.8.1/LService.cs @@ -0,0 +1,188 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.ServiceProcess; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Configuration; +//using System.Windows.Forms; + +namespace LogonService +{ + public partial class LService : ServiceBase + { + private const int WatchInterval = 100; // ms + + ApplicationLoader.PROCESS_INFORMATION procInfo; + //mainForm mForm; + static bool isConsole = false; + private readonly Thread appThread; + private bool isActive = true; + private string logPath; + private bool isLogging = false; + + public string execApp; + public string execAppPath; + + Process executingProc = null; + //readonly Command cmd = Command.Execute; + + //public bool CanShutdown = true; + //public bool CanStop = true; + + public LService(bool isCon) + { + isConsole = isCon; + InitializeComponent(); + + //Get log path + logPath = AppConfig.LogPath; + // Turning log on or off + isLogging = bool.Parse(AppConfig.LogEnabled); + + //var command = AppConfig.OnLogon; + //switch (command) + //{ + // default: + // cmd = Command.Execute; + // execAppPath = command; + // execApp = Path.GetFileNameWithoutExtension(execAppPath); + // appThread = new Thread(Execute_Proc); + // break; + //} + + // Configuring app to run + + execAppPath = AppConfig.OnLogon; + execApp = Path.GetFileNameWithoutExtension(execAppPath); + appThread = new Thread(Execute_Proc); + + appThread.SetApartmentState(ApartmentState.STA); + } + + void Log(string str) + { + if (isLogging) + { + File.AppendAllText(logPath, $"[{DateTime.Now}] {str}\n"); + } + } + + void Execute_Proc() + { + while (isActive) + { + executingProc = Util.TryProc(execApp); + + if (LogonUI.IsLogonMode()) + { + if (executingProc == null) + { + Log($"Logon mode detected - application not running: starting application"); + ApplicationLoader.StartProcessAndBypassUAC(execAppPath, out procInfo); + } + else if (ApplicationLoader.IsNewSession()) + { + Log($"Logon mode detected - application is running: new session detected"); + + try + { + Log($"Killing application"); + executingProc.Kill(); + } + catch (Exception e) + { + Log(e.Message); + Log(e.StackTrace); + } + Log($"Application killed: starting application from scratch"); + ApplicationLoader.StartProcessAndBypassUAC(execAppPath, out procInfo); + } + } + else + { + if (executingProc != null) + { + Log($"User logged in detected: killing application"); + try + { + executingProc.Kill(); + } + catch (Exception e) + { + Log(e.Message); + Log(e.StackTrace); + } + } + } + executingProc = null; + Thread.Sleep(WatchInterval); + } + } + + public void Start() + { + if (string.IsNullOrEmpty(execAppPath)) + { + Log($"Service is started. No comand found to execute in App.config - main thread will not start."); + } + else + { + Log($"Service is started. Founded comand from settings: '{execAppPath}'"); + //Log($"Service is started. Founded comand from settings: {cmd}"); + appThread.Start(); + } + } + + public void LogonWatcherStop() + { + isActive = false; + if (executingProc != null) + { + try + { + executingProc.Kill(); + } + catch (Exception) + { + } + executingProc = null; + } + } + + protected override void OnStart(string[] args) + { + Start(); + base.OnStart(args); + } + + protected override void OnStop() + { + //Log($"OnStop()"); + LogonWatcherStop(); + //Stop(); + base.OnStop(); + } + + protected override void OnShutdown() + { + //Log($"OnShutdown()"); + // Add your save code here + LogonWatcherStop(); + Stop(); + base.OnShutdown(); + } + + //enum Command : byte + //{ + // None, + // Execute, + // LogonUI_WindowHide + //} + } +} diff --git a/LogonService/LogonService_4.8.1/LService.resx b/LogonService/LogonService_4.8.1/LService.resx new file mode 100644 index 0000000..a9d341b --- /dev/null +++ b/LogonService/LogonService_4.8.1/LService.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + False + + \ No newline at end of file diff --git a/LogonService/LogonService_4.8.1/LogonServiceNet4.8.1.csproj b/LogonService/LogonService_4.8.1/LogonServiceNet4.8.1.csproj new file mode 100644 index 0000000..776994e --- /dev/null +++ b/LogonService/LogonService_4.8.1/LogonServiceNet4.8.1.csproj @@ -0,0 +1,179 @@ + + + + + Debug + AnyCPU + {FF02D228-C61A-431B-8EFE-78BCAECB7FC3} + Exe + Properties + LogonService + LogonService + v4.8.1 + 512 + true + 1.1.0.67 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + none + true + bin\Release\ + TRACE + prompt + 4 + + + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + true + + + bin\x86\Release\ + TRACE + true + none + x86 + 7.3 + prompt + true + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + true + + + bin\x64\Release\ + TRACE + true + none + x64 + 7.3 + prompt + true + + + true + bin\ARM64\Debug\ + DEBUG;TRACE + full + ARM64 + 7.3 + prompt + true + + + bin\ARM64\Release\ + TRACE + true + none + ARM64 + 7.3 + prompt + true + + + + + + + + + + + + + + + + + + + + + Component + + + LService.cs + + + + + + + Component + + + ProjectInstaller.cs + + + + + + + + + + + LService.cs + + + ProjectInstaller.cs + + + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file diff --git a/LogonService/LogonService_4.8.1/LogonUI.cs b/LogonService/LogonService_4.8.1/LogonUI.cs new file mode 100644 index 0000000..a03483c --- /dev/null +++ b/LogonService/LogonService_4.8.1/LogonUI.cs @@ -0,0 +1,21 @@ +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace LogonService +{ + static class LogonUI + { + [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] + static extern int GetSystemMetrics(int nIndex); + const int SM_SHUTTINGDOWN = 0x2000; + + const string LogonUIName = "LogonUI"; + const string LogonUIexe = LogonUIName + ".exe"; + const string logonPath = @"C:\Windows\System32\" + LogonUIexe; + + public static bool IsLogonMode() + { + return (GetSystemMetrics(SM_SHUTTINGDOWN) == 0) & Util.IsProcExist(LogonUIName); + } + } +} diff --git a/LogonService/LogonService_4.8.1/Program.cs b/LogonService/LogonService_4.8.1/Program.cs new file mode 100644 index 0000000..50ab859 --- /dev/null +++ b/LogonService/LogonService_4.8.1/Program.cs @@ -0,0 +1,150 @@ +using System; +using System.IO; +using System.ServiceProcess; +using System.Diagnostics; + +namespace LogonService +{ + static class Program + { + /// + /// Главная точка входа для приложения. + /// + static void Main(string[] args) + { + //ServiceBase[] ServicesToRun; + //ServicesToRun = new ServiceBase[] + //{ + // new adsrpService() + //}; + //ServiceBase.Run(ServicesToRun); + if (args != null && args.Length == 1 && args[0].Length > 1 + && (args[0][0] == '-' || args[0][0] == '/')) + { + var serviceName = AppConfig.ServiceName; + + switch (args[0].Substring(1).ToLower()) + { + case "install": + case "i": + try + { + ServiceInstaller.Install(); + Process.Start("net", $"start {serviceName}"); + Console.WriteLine("Service installed and started"); + } + catch (Exception e) + { + Console.WriteLine("Failed to install service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + case "uninstall": + case "u": + try + { + Process.Start("net", $"stop {serviceName}"); + ServiceInstaller.Uninstall(); + Console.WriteLine("Service stopped and uninstalled"); + } + catch (Exception e) + { + Console.WriteLine("Failed to uninstall service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + case "reinstall": + case "r": + try + { + Process.Start("net", $"stop {serviceName}"); + ServiceInstaller.Uninstall(); + ServiceInstaller.Install(); + Process.Start("net", $"start {serviceName}"); + Console.WriteLine("Service stopped and uninstalled"); + } + catch (Exception e) + { + Console.WriteLine("Failed to uninstall service"); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + break; + + + case "start": + Process.Start("net", $"start {serviceName}"); + break; + + case "stop": + Process.Start("net", $"stop {serviceName}"); + break; + + default: + Console.WriteLine("Unrecognized parameters.\n\n" + + " -i /i -install /install — install and start service\n\n" + + " -u /u -uninstall /uninstall — stop and uninstall service\n\n" + + " -r /r -reinstall /reinstall — reinstall service\n\n" + + " -start /start — start service\n\n" + + " -stop /stop — stop service\n\n" + ); + break; + } + } + else + { + try + { + //bool isConsole = Environment.UserInteractive; + LService service = new LService(false); + ServiceBase[] servicesToRun = new ServiceBase[] { service }; + + //if (isConsole) + //{ + // Console.OutputEncoding = Encoding.UTF8; + // Console.CancelKeyPress += (x, y) => service.Stop(); + // try + // { + // service.start(); + // } + // catch + // { + // Console.WriteLine("Initialization unknown error"); + // throw; + // } + + // Console.WriteLine("Service started. Press any key to stop."); + // Console.ReadKey(); + // service.stop(); + // Console.WriteLine("Service stopped. Good bye."); + //} + //else + //{ + ServiceBase.Run(servicesToRun); + //} + } + catch (IOException ex) + { + //log.Error("", ex); + Console.WriteLine("IOException", ex); + } + catch (Exception ex) + { + //log.Fatal("Could not start polling service due to unknown error", ex); + Console.WriteLine("Could not start service due application error", ex); + } + //catch + //{ + // //log.Fatal("Could not start polling service due to unknown error", ex); + // Console.WriteLine("Could not start service due to unknown error"); + //} + } + } + + + } +} diff --git a/LogonService/LogonService_4.8.1/ProjectInstaller.Designer.cs b/LogonService/LogonService_4.8.1/ProjectInstaller.Designer.cs new file mode 100644 index 0000000..4a8c3e7 --- /dev/null +++ b/LogonService/LogonService_4.8.1/ProjectInstaller.Designer.cs @@ -0,0 +1,61 @@ +namespace LogonService +{ + partial class ProjectInstaller + { + /// + /// Требуется переменная конструктора. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Освободить все используемые ресурсы. + /// + /// истинно, если управляемый ресурс должен быть удален; иначе ложно. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Код, автоматически созданный конструктором компонентов + + /// + /// Обязательный метод для поддержки конструктора - не изменяйте + /// содержимое данного метода при помощи редактора кода. + /// + private void InitializeComponent() + { + this.adsprServiceInstaller = new System.ServiceProcess.ServiceProcessInstaller(); + this.LogonServiceInstaller = new System.ServiceProcess.ServiceInstaller(); + // + // adsprServiceInstaller + // + this.adsprServiceInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem; + this.adsprServiceInstaller.Password = "lsrv"; + this.adsprServiceInstaller.Username = "lsrv"; + // + // LogonServiceInstaller + // + this.LogonServiceInstaller.Description = "Logon Service for running applications on logon screen"; + this.LogonServiceInstaller.DisplayName = "Logon Service"; + this.LogonServiceInstaller.ServiceName = "LogonService"; + this.LogonServiceInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; + // + // ProjectInstaller + // + this.Installers.AddRange(new System.Configuration.Install.Installer[] { + this.adsprServiceInstaller, + this.LogonServiceInstaller}); + + } + + #endregion + + private System.ServiceProcess.ServiceProcessInstaller adsprServiceInstaller; + private System.ServiceProcess.ServiceInstaller LogonServiceInstaller; + + } +} diff --git a/LogonService/LogonService_4.8.1/ProjectInstaller.cs b/LogonService/LogonService_4.8.1/ProjectInstaller.cs new file mode 100644 index 0000000..f97643a --- /dev/null +++ b/LogonService/LogonService_4.8.1/ProjectInstaller.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; +using System.Configuration; + +namespace LogonService +{ + [RunInstaller(true)] + public partial class ProjectInstaller : System.Configuration.Install.Installer + { + public ProjectInstaller() + { + InitializeComponent(); + + LogonServiceInstaller.Description = AppConfig.Description; + LogonServiceInstaller.DisplayName = AppConfig.DisplayName; + LogonServiceInstaller.ServiceName = AppConfig.ServiceName; + } + } +} diff --git a/LogonService/LogonService_4.8.1/ProjectInstaller.resx b/LogonService/LogonService_4.8.1/ProjectInstaller.resx new file mode 100644 index 0000000..e7b532b --- /dev/null +++ b/LogonService/LogonService_4.8.1/ProjectInstaller.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 63 + + + 186, 22 + + + False + + \ No newline at end of file diff --git a/LogonService/LogonService_4.8.1/Properties/AssemblyInfo.cs b/LogonService/LogonService_4.8.1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7e84100 --- /dev/null +++ b/LogonService/LogonService_4.8.1/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется с помощью +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("Logon service")] +[assembly: AssemblyDescription("Logon service")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("VoidVolker")] +[assembly: AssemblyProduct("Logon service")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми +// для COM-компонентов. Если требуется обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("5d52f9b6-81b1-4fbc-aa52-346ee4585727")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.1.0.67")] +[assembly: AssemblyFileVersion("1.1.0.67")] + +[assembly: AssemblyInformationalVersion("0.0.0.63")] \ No newline at end of file diff --git a/LogonService/LogonService_4.8.1/serviceInstaller.cs b/LogonService/LogonService_4.8.1/serviceInstaller.cs new file mode 100644 index 0000000..913a8a9 --- /dev/null +++ b/LogonService/LogonService_4.8.1/serviceInstaller.cs @@ -0,0 +1,35 @@ +using System.Configuration.Install; +using System.Reflection; + +namespace LogonService +{ + class ServiceInstaller + { + //private static readonly ILog log = LogManager.GetLogger(typeof(Program)); + private static readonly string exePath = Assembly.GetExecutingAssembly().Location; + + public static void Install() + { + ManagedInstallerClass.InstallHelper(new[] { exePath }); + //try { ManagedInstallerClass.InstallHelper(new[] { exePath }); } + //catch { return false; } + //return true; + } + + public static void Uninstall() + { + ManagedInstallerClass.InstallHelper(new[] { "/u", exePath }); + //if( EventLog.Exists(adsrpService.evLogSource) ) + //{ + // EventLog.Delete(adsrpService.evLogSource); + //} + //if (EventLog.SourceExists(adsrpService.evLogSource)) + //{ + // EventLog.DeleteEventSource(adsrpService.evLogSource); + //} + //try { ManagedInstallerClass.InstallHelper(new[] { "/u", exePath }); } + //catch { return false; } + //return true; + } + } +} diff --git a/LogonService/LogonService_4.8.1/util.cs b/LogonService/LogonService_4.8.1/util.cs new file mode 100644 index 0000000..d93a136 --- /dev/null +++ b/LogonService/LogonService_4.8.1/util.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; + +namespace LogonService +{ + static class Util + { + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsWindowVisible(IntPtr hWnd); + + + private const int SW_HIDE = 0; + private const int SW_SHOW = 5; + [DllImport("User32")] + private static extern int ShowWindow(IntPtr hwnd, int nCmdShow); + + public static bool IsProcExist(string name) + { + Process[] arrProcesses = Process.GetProcessesByName(name); + return arrProcesses.Length > 0; + } + + public static Process TryProc(string name) + { + Process[] arrProcesses = Process.GetProcessesByName(name); + if (arrProcesses.Length > 0) + { + return arrProcesses[0]; + } + else + { + return null; + } + } + } +} diff --git a/README.md b/README.md index 19a33ce..8871fac 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,33 @@ -# Windows Logon service - -This service is able to run any application on user login screen. I spend several weeks to collect all solutions from internet into one working project. Using specific WinAPI calls this service collects info about logon session and using this info runs application in logon session. PR are welcome! - -![LogonApplication](https://github.com/VoidVolker/Windows-logon-service/assets/5086438/23dfd564-a8b7-43d2-a96d-3205aa40c341) - -# How to use -1. Find in code LogonUI string and replace to your application -2. Build solution -3. Install service - -# Tested in next Operating systems: -Windows XP SP3, 7, 8.1, 10 - -TODO: -1. Write documentation (just run in console) -2. Write documentation for code -3. Move running aplication path to settings for standalone use -4. Make code more logical (?) -5. Publish in repository as library (?) +# Windows Logon service + +This service is able to run any application on user login screen. I spend several weeks to collect all solutions from internet into one working project. Using specific WinAPI calls this service collects info about logon session and using this info runs application in logon session. PR are welcome! + +![LogonApplication](https://github.com/VoidVolker/Windows-logon-service/assets/5086438/23dfd564-a8b7-43d2-a96d-3205aa40c341) + +# How to use +1. Download archive for your platform at [Releases](https://github.com/VoidVolker/Windows-logon-service/releases) paga +1. Edit configuration file `LogonService.exe.config`: + - `OnLogon` - aplication to run at logon screen (mode: immediately restart app if it die) + - `LogEnabled` - turn on/off logging + - `LogPath` - full file path to log file (default: `exe dir/log.txt` - not current dir, because for service it will be system32) + - `Description` - service description + - `DisplayName`- service display name + - `ServiceName` - service system level name (no spaces!) + +1. Install service in command line: + +```cmd +LogonService.exe /install +``` + +# Available commands + +- `-i` `/i` `-install` `/install` - install and start service +- `-u` `/u` `-uninstall` `/uninstall` - stop and uninstall service +- `-r` `/r` `-reinstall` `/reinstall` - reinstall service +- `-start` `/start` - start service +- `-stop` `/stop` - stop service + +# Tested in next Operating systems: + +Windows XP SP3, 7, 8.1, 10