From 8f8ac37ac31b884d0ca439869987873f5e1ff86d Mon Sep 17 00:00:00 2001 From: Thomas de Roo Date: Mon, 12 Jul 2021 16:14:24 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 63 ++++ .gitignore | 340 ++++++++++++++++++ SyncProfilePicture.sln | 37 ++ SyncProfilePicture/App.config | 6 + SyncProfilePicture/Program.cs | 313 ++++++++++++++++ SyncProfilePicture/Properties/AssemblyInfo.cs | 36 ++ .../Properties/Settings.Designer.cs | 26 ++ .../Properties/Settings.settings | 6 + SyncProfilePicture/SyncProfilePicture.csproj | 102 ++++++ SyncProfilePicture/SyncProfilePicture.ico | Bin 0 -> 105644 bytes 10 files changed, 929 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 SyncProfilePicture.sln create mode 100644 SyncProfilePicture/App.config create mode 100644 SyncProfilePicture/Program.cs create mode 100644 SyncProfilePicture/Properties/AssemblyInfo.cs create mode 100644 SyncProfilePicture/Properties/Settings.Designer.cs create mode 100644 SyncProfilePicture/Properties/Settings.settings create mode 100644 SyncProfilePicture/SyncProfilePicture.csproj create mode 100644 SyncProfilePicture/SyncProfilePicture.ico diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ce6fdd --- /dev/null +++ b/.gitignore @@ -0,0 +1,340 @@ +## 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 +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +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/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.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 +*- Backup*.rdl + +# 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 personal settings +.cr/personal + +# 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/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb \ No newline at end of file diff --git a/SyncProfilePicture.sln b/SyncProfilePicture.sln new file mode 100644 index 0000000..092dd2f --- /dev/null +++ b/SyncProfilePicture.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31005.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyncProfilePicture", "SyncProfilePicture\SyncProfilePicture.csproj", "{B55493BD-5C1D-4426-A725-4C3880884039}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|x64.ActiveCfg = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|x64.Build.0 = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|x86.ActiveCfg = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Debug|x86.Build.0 = Debug|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|Any CPU.Build.0 = Release|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|x64.ActiveCfg = Release|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|x64.Build.0 = Release|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|x86.ActiveCfg = Release|Any CPU + {B55493BD-5C1D-4426-A725-4C3880884039}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7DC3CFB0-52C5-47DF-AFF0-84B5679A9108} + EndGlobalSection +EndGlobal diff --git a/SyncProfilePicture/App.config b/SyncProfilePicture/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/SyncProfilePicture/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SyncProfilePicture/Program.cs b/SyncProfilePicture/Program.cs new file mode 100644 index 0000000..9b3969d --- /dev/null +++ b/SyncProfilePicture/Program.cs @@ -0,0 +1,313 @@ +using System; +using System.Collections.Generic; +using System.DirectoryServices; +using System.IO; +using System.Drawing; +using System.Drawing.Imaging; +using Microsoft.Win32; +using System.Security.Principal; +using System.Drawing.Drawing2D; + +namespace SyncProfilePicture +{ + class Program + { + + + public static void SetLocal(Image image, string userSid, string profilePictureFolder, bool doVerbose) + { + if (doVerbose) + { + Console.WriteLine("Creating folder " + profilePictureFolder); + } + DirectoryInfo newFolder = Directory.CreateDirectory(profilePictureFolder); + newFolder.Attributes = FileAttributes.Directory | FileAttributes.Hidden; + + if (doVerbose) + { + Console.WriteLine($"Setting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AccountPicture\\Users\\{userSid}"); + } + RegistryKey localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); + RegistryKey userKey = localMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AccountPicture\\Users", RegistryKeyPermissionCheck.ReadWriteSubTree); + userKey.CreateSubKey(userSid); + RegistryKey sidKey = userKey.OpenSubKey(userSid, RegistryKeyPermissionCheck.ReadWriteSubTree); + List imageSizes = new List + { + "1080", + "192", + "208", + "240", + "32", + "40", + "424", + "448", + "48", + "64", + "96" + }; + foreach (string imageSize in imageSizes) + { + if (doVerbose) + { + Console.WriteLine($"Saving profile picture to {profilePictureFolder}\\{userSid}-Image{imageSize}.jpg"); + } + Int32 imageSizeInt = Int32.Parse(imageSize); + sidKey.SetValue($"Image{imageSize}", $"{profilePictureFolder}\\{userSid}-Image{imageSize}.jpg"); + Image imageResized = new Bitmap(image, new Size(imageSizeInt, imageSizeInt)); + imageResized.Save($"{profilePictureFolder}\\{userSid}-Image{imageSize}.jpg", ImageFormat.Jpeg); + }; + sidKey.Close(); + userKey.Close(); + if (doVerbose) + { + Console.WriteLine("Local profile picture set."); + } + } + public static string ShrinkImage(string path) + { + Image image = Image.FromFile(path); + string newPath = path; + double fileSize = new FileInfo(path).Length / 1024; + int oldHeight = image.Height; + while (fileSize > 100) { + if (path != newPath) + { + File.Delete(newPath); + } + int newHeight = (Int32)(oldHeight * 0.9); + Image newImage = new Bitmap(image, new Size(newHeight, newHeight)); + newPath = $"{Path.GetTempPath()}\\{Path.GetFileNameWithoutExtension(path)}-{newHeight}.jpg"; + newImage.Save(newPath, ImageFormat.Jpeg); + fileSize = new FileInfo(newPath).Length / 1024; + oldHeight = newHeight; + } + return newPath; + } + public static void SetAd(string profilePicturePath, DirectoryEntry userEntry, string userAttribute, bool doVerbose) + { + if (doVerbose) + { + Console.WriteLine($"Using picture file {profilePicturePath}"); + } + Image profilePicture = Image.FromFile(profilePicturePath); + double fileSizeKB = new FileInfo(profilePicturePath).Length / 1024; + { + Console.WriteLine($"Profile picture size is {fileSizeKB}KB"); + } + if (fileSizeKB > 100) + { + profilePicturePath = ShrinkImage(profilePicturePath); + profilePicture = Image.FromFile(profilePicturePath); + fileSizeKB = new FileInfo(profilePicturePath).Length / 1024; + { + Console.WriteLine($"Profile picture resized, using {profilePicturePath}"); + Console.WriteLine($"Profile picture size is {fileSizeKB}KB"); + } + + } + var ms = new MemoryStream(); + profilePicture.Save(ms, profilePicture.RawFormat); + var profilePictureArray = ms.ToArray(); + userEntry.Properties[userAttribute].Clear(); + userEntry.CommitChanges(); + if (doVerbose) + { + Console.WriteLine("AD profile picture cleared."); + } + userEntry.Properties[userAttribute].Add(profilePictureArray); + userEntry.CommitChanges(); + if (doVerbose) + { + Console.WriteLine("AD profile picture updated."); + } + } + static void Main(string[] args) + { + //defaults + string pictureSize = "1080"; + string userAttribute = "thumbnailPhoto"; + bool doAdToLocal = false; + bool doLocalToAd = false; + bool doVerbose = false; + bool doFileToLocal = false; + bool doAdToFile = false; + bool doOtherUser = false; + bool doFileToAd = false; + string importPicturePath = null; + string exportPicturePath = null; + string userName = null; + string userSid = null; + + for (int i = 0; i < args.Length; i++) + { + if (String.Equals(args[i], "-username")) + { + + doOtherUser = true; + userName = args[(i + 1)]; + + } + if (String.Equals(args[i], "-file2local")) + { + Console.WriteLine("Setting AD profile picture from file."); + doFileToLocal = true; + importPicturePath = args[(i + 1)]; + + } + if (String.Equals(args[i], "-file2ad")) + { + Console.WriteLine("Setting local profile picture from file."); + doFileToAd = true; + importPicturePath = args[(i + 1)]; + + } + if (String.Equals(args[i], "-ad2file")) + { + Console.WriteLine("Exporting profile picture from AD to file."); + doAdToFile = true; + exportPicturePath = args[(i + 1)]; + + } + if (String.Equals(args[i], "-verbose")) + { + Console.WriteLine("Verbose messages selected."); + doVerbose = true; + } + if (String.Equals( args[i], "-ad2local")) + { + if (doVerbose) + { + Console.WriteLine("Saving profile picture from AD to local"); + } + doAdToLocal = true; + } + if (String.Equals(args[i], "-local2ad")) + { + if (doVerbose) + { + Console.WriteLine("Saving profile picture from local to AD"); + } + doLocalToAd = true; + } + if (String.Equals(args[i], "-jpegPhoto")) + { + if (doVerbose) + { + Console.WriteLine("Using jpegPhoto as AD user attribute"); + } + userAttribute = "jpegPhoto"; + } + if (String.Equals(args[i], "-picturesize")) + { + pictureSize = args[(i + 1)]; + if (doVerbose) + { + Console.WriteLine($"Using picture size {pictureSize}"); + } + } + } + if (doAdToLocal & doLocalToAd) + { + Console.WriteLine("Error: both -ad2local and -local2ad used. Choose only one option"); + return; + } + if (!doAdToLocal & !doLocalToAd & !doFileToLocal & !doAdToFile & !doFileToAd) + { + Console.WriteLine("Usage:\r\nSyncProfilePicture [-ad2local | -local2ad | -file2local | -ad2file] [-picturesize ] [-username ] [-jpegPhoto] [-verbose]"); + return; + } + + //Connect to AD + DirectoryEntry RootDirEntry = new DirectoryEntry("LDAP://RootDSE"); + var distinguishedName = RootDirEntry.Properties["defaultNamingContext"].Value; + if (doVerbose) + { + Console.WriteLine("Using ActiveDirectory domain " + distinguishedName); + } + var myDE = new DirectoryEntry("LDAP://" + distinguishedName); + if (!doOtherUser) + { + userName = Environment.UserName; + } + DirectorySearcher directorySearcher = new DirectorySearcher(myDE, String.Format("(sAMAccountName={0})", userName)); + SearchResult searchResult = directorySearcher.FindOne(); + DirectoryEntry userEntry = searchResult.GetDirectoryEntry(); + + //Find username & SID + if (!doOtherUser) + { + userSid = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; + } + else + { + userSid = new SecurityIdentifier((byte[])userEntry.Properties["objectSid"].Value, 0).ToString(); + } + if (doVerbose) + { + Console.WriteLine("Using username " + userName); + Console.WriteLine("using SID " + userSid); + } + + + string profilePictureFolder = $"{Environment.GetEnvironmentVariable("Public")}\\AccountPictures\\{userSid}"; + if (doVerbose) + { + Console.WriteLine("using profile picture folder " + profilePictureFolder); + } + + + if (doAdToLocal) + { + var jpegByteArray = userEntry.Properties[userAttribute].Value; + Image image = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray)); + SetLocal(image, userSid, profilePictureFolder, doVerbose); + } + if (doAdToFile) + { + if (doVerbose) + { + Console.WriteLine("Saving AD profile picture to " + exportPicturePath); + } + var jpegByteArray = userEntry.Properties[userAttribute].Value; + Image image = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray)); + image.Save(exportPicturePath, ImageFormat.Jpeg); + } + if (doFileToLocal) + { + if (File.Exists(importPicturePath)) + { + Image image = Image.FromFile(importPicturePath); + SetLocal(image, userSid, profilePictureFolder, doVerbose); + } + else + { + Console.WriteLine($"Error: {importPicturePath} not found"); + } + } + if (doFileToAd) + { + if (File.Exists(importPicturePath)) + { + Image image = Image.FromFile(importPicturePath); + SetAd(importPicturePath, userEntry, userAttribute, doVerbose); + } + else + { + Console.WriteLine($"Error: {importPicturePath} not found"); + } + } + if (doLocalToAd) + { + RegistryKey localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); + RegistryKey userKey = localMachine.OpenSubKey($"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AccountPicture\\Users\\{userSid}", RegistryKeyPermissionCheck.ReadWriteSubTree); + string profilePicturePath = (string)userKey.GetValue($"Image{pictureSize}"); + SetAd(profilePicturePath, userEntry, userAttribute, doVerbose); + + } + if (doVerbose) + { + Console.WriteLine("Done."); + } + } + } +} diff --git a/SyncProfilePicture/Properties/AssemblyInfo.cs b/SyncProfilePicture/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..70b7274 --- /dev/null +++ b/SyncProfilePicture/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SyncProfilePicture")] +[assembly: AssemblyDescription("Sunc AD thumbnailPhoto to Windows 10 Profile Picture")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Thomas de Roo")] +[assembly: AssemblyProduct("SyncProfilePicture")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b55493bd-5c1d-4426-a725-4c3880884039")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("21.7.9.0")] +[assembly: AssemblyFileVersion("21.7.9.0")] diff --git a/SyncProfilePicture/Properties/Settings.Designer.cs b/SyncProfilePicture/Properties/Settings.Designer.cs new file mode 100644 index 0000000..616cac2 --- /dev/null +++ b/SyncProfilePicture/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SyncProfilePicture.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/SyncProfilePicture/Properties/Settings.settings b/SyncProfilePicture/Properties/Settings.settings new file mode 100644 index 0000000..049245f --- /dev/null +++ b/SyncProfilePicture/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/SyncProfilePicture/SyncProfilePicture.csproj b/SyncProfilePicture/SyncProfilePicture.csproj new file mode 100644 index 0000000..0cc5650 --- /dev/null +++ b/SyncProfilePicture/SyncProfilePicture.csproj @@ -0,0 +1,102 @@ + + + + + Debug + AnyCPU + {B55493BD-5C1D-4426-A725-4C3880884039} + Exe + SyncProfilePicture + SyncProfilePicture + v4.7.2 + 512 + true + true + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 0.1.210709.0 + false + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + SyncProfilePicture.Program + + + SyncProfilePicture.ico + + + + + + + + + + + + + + + + + + True + True + Settings.settings + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + False + Microsoft .NET Framework 4.7.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + + \ No newline at end of file diff --git a/SyncProfilePicture/SyncProfilePicture.ico b/SyncProfilePicture/SyncProfilePicture.ico new file mode 100644 index 0000000000000000000000000000000000000000..fd0e0852281ffc9f90e94d6a2ce09af983e56e73 GIT binary patch literal 105644 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