diff --git a/ThisAssembly.sln b/ThisAssembly.sln
index a282d162..38bda251 100644
--- a/ThisAssembly.sln
+++ b/ThisAssembly.sln
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThisAssembly.Git", "src\Thi
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Shared", "src\Shared\Shared.shproj", "{8E0F2A43-C9AF-4E46-BF70-CF8645371C12}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThisAssembly.Vsix", "src\ThisAssembly.Vsix\ThisAssembly.Vsix.csproj", "{0C4A87B0-FBD7-42BE-A504-DBBC55132146}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -65,6 +67,10 @@ Global
{F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F34F8470-7C60-4BB8-ACB5-569D6D0F6A46}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C4A87B0-FBD7-42BE-A504-DBBC55132146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C4A87B0-FBD7-42BE-A504-DBBC55132146}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C4A87B0-FBD7-42BE-A504-DBBC55132146}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C4A87B0-FBD7-42BE-A504-DBBC55132146}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -73,6 +79,7 @@ Global
SolutionGuid = {ADF2DC9F-5F77-4F6E-8804-CFF5892CD064}
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ src\Shared\Shared.projitems*{0c4a87b0-fbd7-42be-a504-dbbc55132146}*SharedItemsImports = 5
src\Shared\Shared.projitems*{14d0c5ba-8410-4454-87a2-7bf5993e1ea2}*SharedItemsImports = 5
src\Shared\Shared.projitems*{31c53cce-13fc-4890-803a-85cd146b909b}*SharedItemsImports = 5
src\Shared\Shared.projitems*{3e7158b5-bfef-4416-8226-9096c7c98268}*SharedItemsImports = 5
diff --git a/img/ThisAssembly.Vsix.png b/img/ThisAssembly.Vsix.png
new file mode 100644
index 00000000..0ab2e11b
Binary files /dev/null and b/img/ThisAssembly.Vsix.png differ
diff --git a/src/ThisAssembly.Vsix/ThisAssembly.Vsix.Pack.targets b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.Pack.targets
new file mode 100644
index 00000000..425e1ba1
--- /dev/null
+++ b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.Pack.targets
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ThisAssembly.Vsix/ThisAssembly.Vsix.csproj b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.csproj
new file mode 100644
index 00000000..8bc5ee27
--- /dev/null
+++ b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.csproj
@@ -0,0 +1,41 @@
+
+
+
+ netstandard2.0
+ latest
+ true
+ false
+ $(PackageTags) vsix
+
+
+
+ ThisAssembly.Vsix
+ This package generates a static `ThisAssembly.Vsix` class with public
+constants exposing key VSIX manifest properties. For example:
+
+ partial class ThisAssembly
+ {
+ public static partial class Vsix
+ {
+ public const string Id = "MyVsix";
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ThisAssembly.Vsix/ThisAssembly.Vsix.props b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.props
new file mode 100644
index 00000000..39c849a1
--- /dev/null
+++ b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.props
@@ -0,0 +1,8 @@
+
+
+
+
+ false
+
+
+
\ No newline at end of file
diff --git a/src/ThisAssembly.Vsix/ThisAssembly.Vsix.targets b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.targets
new file mode 100644
index 00000000..118a2499
--- /dev/null
+++ b/src/ThisAssembly.Vsix/ThisAssembly.Vsix.targets
@@ -0,0 +1,123 @@
+
+
+
+ <Namespace Prefix='vs' Uri='http://schemas.microsoft.com/developer/vsx-schema/2011'/>
+ <Namespace Prefix='vs' Uri='http://schemas.microsoft.com/developer/vsx-schema/2010'/>
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PackageId)
+ $(AssemblyName)
+
+
+
+
+
+ $(Version)
+
+
+
+
+
+ $(Title)
+
+
+
+
+
+ $(Description)
+
+
+
+
+
+ $(Product)
+
+
+
+
+
+ $(Company)
+
+
+
+
+
+ $(NeutralLanguage)
+ en-US
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ThisAssembly.Vsix/readme.md b/src/ThisAssembly.Vsix/readme.md
new file mode 100644
index 00000000..313a2d51
--- /dev/null
+++ b/src/ThisAssembly.Vsix/readme.md
@@ -0,0 +1,66 @@
+
+
+This package generates a static `ThisAssembly.Vsix` class with public
+constants exposing key VSIX manifest properties.
+
+![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Vsix.png)
+
+For example:
+
+```csharp
+ partial class ThisAssembly
+ {
+ public static partial class Vsix
+ {
+ public const string Id = "MyVsix";
+ }
+ }
+```
+
+In addition to making the [VSIX manifest metadata](https://learn.microsoft.com/en-us/visualstudio/extensibility/vsix-extension-schema-2-0-reference?view=vs-2022#metadata-element)
+properties available as constants, the package also provides targets for those properties
+with sensible defaults from project properties so that the manifest can leverage
+[placeolder syntax](https://learn.microsoft.com/en-us/visualstudio/extensibility/vsix-extension-schema-2-0-reference?view=vs-2022#metadata-element)
+and avoid duplication.
+
+For example, the following `source.extension.vsixmanifest` uses values from MSBuild exclusively:
+```xml
+
+
+
+
+ |%CurrentProject%;VsixDisplayName|
+ |%CurrentProject%;VsixDescription|
+
+ ...
+
+```
+
+The available properties and their default values are:
+
+| Name | Default Value |
+|-------------------|-----------------------------------|
+| VsixID | $(PackageId) or $(AssemblyName) |
+| VsixVersion | $(Version) |
+| VsixDisplayName | $(Title) |
+| VsixDescription | $(Description) |
+| VsixProduct | $(Product) |
+| VsixPublisher | $(Company) |
+| VsixLanguage | $(NeutralLanguage) or 'en-US' |
+| VsixDescription | $(Description) |
+
+As shown in the example above, the syntax for using these properties from the `.vsxmanifest` is
+`|%CurrentProject%;[PROPERTY]|`. This is because the package defines a corresponding target to
+retrieve each of the above properties. You can provide a different value for each property via
+MSBuild as usual, of course.
+
+Since the `$(PackageId)` property can be used as the VSIX ID, the `Pack` target is redefined to
+mean `CreateVsixManifest`, so "packing" the VSIX is just a matter of right-clicking the VSIX
+project and selecting "Pack".
+
+
+
+
+
\ No newline at end of file