Accoding to Andy Wigley on this video https://www.microsoftvirtualacademy.com/en-US/training-courses/a-developer-s-guide-to-windows-10-12618 (look in additional resources -> Localization), UPW apps download only the culture resources they need.
I'm writing an app that uses resource files not only to translate UI but also generate files for the user. User may want to generate files in different culture than the one the OS uses. How I can assure that e.g. if my system is in en-US I will be able to get resources in french?
I may use own XML files that all will be included in the app. But some of the resource for sure will be needed also in UI, so I don't want to duplicate the resources and have to translate them twice.
Rob's answer would work great for a new app, but it didn't work for me, as I had already shipped a previous version of the app as a bundled package. If you then try to switch to a non-bundled package, the store submission portal gives the error:
A previous submission for this app was released with a Windows 10 appxbundle. Subsequent submissions must continue to contain a Windows 10 appxbundle.
After reverse-engineering far too much of the build system, I found enough clues to discover this well-hidden documentation: https://msdn.microsoft.com/en-us/library/dn482043.aspx
Following the steps there, you'll still create a bundled package, but the toolchain won't use Language as a qualifier on which to separate out different bundles. In other words, the neutral package will have all the languages in it, while still bundling satellite packages for Scale (or whatever you like).
In case the MSDN page vanishes, the punchline is that you can override <AppxBundleAutoResourcePackageQualifiers> in your msbuild file to remove the Langauge qualifier:
<AppxBundleAutoResourcePackageQualifiers>Scale</AppxBundleAutoResourcePackageQualifiers>
If you do not want to separate out resources into separately downloadable bundles then you don't need to. When you build the app package you can choose to never create bundles so all resources are included in the main package.
See step six in Create an app package at https://msdn.microsoft.com/en-us/library/hh454036.aspx , but choose "never" instead of "always".
Related
I have a windows forms application that is deployed to two different locations.
Intranet - ClickOnce
Internet - Installed on a citrix farm through Windows installer
I display ClickOnce version number for click-once deployed versionApplicationDeployment.IsNetworkDeployed.
if (ApplicationDeployment.IsNetworkDeployed)
return ApplicationDeployment.CurrentDeployment.CurrentVersion;
But for the non-click application, I am not sure how to retrieve clickonce version unless I hardcode the version number in assembly info.
Is there an automatic way of retrieve ClickOnce version number for non-clickonce deployed version?
Add an assembly reference to System.Deployment to your project.
Import the namespace in your class file:
VB.NET:
Imports System.Deployment.Application
C#:
using System.Deployment.Application;
Retrieve the ClickOnce version from the CurrentVersion property.
You can obtain the current version from the ApplicationDeployment.CurrentDeployment.CurrentVersion property. This returns a System.Version object.
Note (from MSDN):
CurrentVersion will differ from UpdatedVersion if a new update has
been installed but you have not yet called Restart. If the deployment
manifest is configured to perform automatic updates, you can compare
these two values to determine if you should restart the application.
NOTE: The CurrentDeployment static property is only valid when the application has been deployed with ClickOnce. Therefore before you access this property, you should check the ApplicationDeployment.IsNetworkDeployed property first. It will always return a false in the debug environment.
VB.NET:
Dim myVersion as Version
If ApplicationDeployment.IsNetworkDeployed Then
myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion
End If
C#:
Version myVersion;
if (ApplicationDeployment.IsNetworkDeployed)
myVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
Use the Version object:
From here on you can use the version information in a label, say on an "About" form, in this way:
VB.NET:
versionLabel.Text = String.Concat("ClickOnce published Version: v", myVersion)
C#:
versionLabel.Text = string.Concat("ClickOnce published Version: v", myVersion);
(Version objects are formatted as a four-part number (major.minor.build.revision).)
No I do not believe that there is a way. I believe the ClickOnce information comes from the manifest which will only be available in a ClickOnce deployment. I think that hard coding the version number is your best option.
I would simply make the assembly version of the main assembly the same as the CLickOnce version every time you put out a new version. Then when it runs as a non-clickonce application, just use Reflection to pick up the assembly version.
Try thread verification:
if (ApplicationDeployment.IsNetworkDeployed)
{
if (ApplicationDeployment.CurrentDeployment.CurrentVersion != ApplicationDeployment.CurrentDeployment.UpdatedVersion)
{
Application.ExitThread();
Application.Restart();
}
}
not that it matters three years later, but I ended up just parsing the manifest file with xml reader.
To expand on RobinDotNet's solution:
Protip: You can automatically run a program or script to do this for you from inside the .csproj file MSBuild configuration every time you build. I did this for one Web application that I am currently maintaining, executing a Cygwin bash shell script to do some version control h4x to calculate a version number from Git history, then pre-process the assembly information source file compiled into the build output.
A similar thing could be done to parse the ClickOnce version number out of the project file i.e., Project.PropertyGroup.ApplicationRevision and Project.PropertyGroup.ApplicationVersion (albeit I don't know what the version string means, but you can just guess until it breaks and fix it then) and insert that version information into the assembly information.
I don't know when the ClickOnce version is bumped, but probably after the build process so you may need to tinker with this solution to get the new number compiled in. I guess there's always /*h4x*/ +1.
I used Cygwin because *nix scripting is so much better than Windows and interpreted code saves you the trouble of building your pre-build program before building, but you could write the program using whatever technology you wanted (including C#/.NET). The command line for the pre-processor goes inside the PreBuildEvent:
<PropertyGroup>
<PreBuildEvent>
$(CYGWIN_ROOT)bin\bash.exe --login -c refresh-version
</PreBuildEvent>
</PropertyGroup>
As you'd imagine, this happens before the build stage so you can effectively pre-process your source code just before compiling it. I didn't want to be automatically editing the Properties\AssemblyInfo.cs file so to play it safe what I did was create a Properties\VersionInfo.base.cs file that contained a text template of a class with version information and was marked as BuildAction=None in the project settings so that it wasn't compiled with the project:
using System.Reflection;
using EngiCan.Common.Properties;
[assembly: AssemblyVersion("0.$REVNUM_DIV(100)$.$REVNUM_MOD(100)$.$DIRTY$")]
[assembly: AssemblyRevisionIdentifier("$REVID$")]
(A very dirty, poor-man's placeholder syntax resembling Windows' environment variables with some additional h4x thrown in was used for simplicity's/complexity's sake)
AssemblyRevisionIdentifierAttribute was a custom attribute that I created to hold the Git SHA1 since it is much more meaningful to developers than a.b.c.d.
My refresh-version program would then copy that file to Properties\VersionInfo.cs, and then do the substitution of the version information that it already calculated/parsed (I used sed(1) for the substitution, which was another benefit to using Cygwin). Properties\VersionInfo.cs was compiled into the program. That file can start out empty and you should ignore it by your version control system because it is automatically changing and the information to generate it is already stored elsewhere.
Hard code, or... Keep track on your versions (File, Assembly, Deploy) in a database. Make a call to the database with your Assembly and get the Deploy version.
This assumes that you are incrementing your versions in a logical way such that each version type has a relationship. It's a lot of work for such a minor problem. I'd personally go with Jared's solution; although I hate hard coding anything.
Using a build component, you could read the click-once version from the project file and write it automatically to the assembly info so both of them are in sync.
Solution for .NET (Core) 7 and higher
On .net Core, you can read the version number from the environment variable ClickOnce_CurrentVersion.
string versionString = Environment.GetEnvironmentVariable("ClickOnce_CurrentVersion") ?? "0.0.0.0";
Version version= Version.Parse(versionString);
MessageBox.Show(version.ToString());
See documentation
In our company we have a software program that operates the machines that we produce. The application (HMI) that is running on a WES7 OS is programmed in C#. Because our machines are shipped all over the world, the language of the HMI can be adjusted by clicking on a language button.
The HMI software is written by a third company but we have it in our own control now. The machine's we deliver might have project specific "fault" messages and must be added to the HMI. This means that these specific "fault messages" must be added to the resources.resx file. But for as far as I know, this can only be done from Visual Studio, do a build and a new file ExternalResources.xap file is created with all translations (Multilanguage).
We don't want a specific application for each customer or do a build on the project for only creating the ExternalResources.xap file. So I'm wondering if there are tools available that run standalone (no Visual Studio needed) and that can create the ExternalResources.xap file.
We don't need to add sources to the resources file, but only change the value of a source on project wish. I hope I made my point clear and someone knows a solution.
Edit:
I need to generatoe the ExternalResources.xap file. When you open this file, all locations available are shown in folders, and within this folders, there are *.recourses.dll files. Those files do I need to generate!
You may use Resgen.exe
Or develop some tool for that, here is a useful sample Extended Strongly Typed Resource Generator
Hope this helps.
We have a C# desktop application which we run for clients on various servers on a software as a service model. We are still on dot net framework 2.
The software has a architecture in which we have an independent application to catch external data thrown by some server. Then an application to make calculations based on it. Also one more application on which the client sees the output. The link between the 3 applications is another application which communicates with the DB.
The 4 solutions are on a SVN for sourcecontrol. But the release management is still manual and the patches are made manually by checking the log and including the dlls, pdbs, xml. etc for the projects for which the code has changed.
There is no assembly versioning implemented and the patch or release management is just done in the dark.
I want to know what is the industry practice for generating automatic patches from the code. Also I want a patch for each revision in the SVN. Also is assembly versioning helpful in this?
I have read much about continuous integration but it fails because we do not have unit tests and other fancy code to moniter the correctness of code.
The only thing at this time I would be interested is to implement a way to make patches which can be applied and removed easily. Also I want to know a way to determine the way we can monitor which release is at which level(or what patches have been applied) by some automated way rather than maintaining a log manually.
We use a build script which creates a SvnVersion.cs file containing the last commited revision. This file is placed in the root of the solution, and then added to all projects in the solution (but added as a link, not copied).
The template for the file (SvnVersion.Template.cs) looks like this:
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.$WCREV$")]
[assembly: AssemblyFileVersion("1.0.0.$WCREV$")]
And we simply use TortoiseSVN to fill these placeholders in a batch script:
type "%TRUNKPATH%SvnVersion.Template.cs" > "%TRUNKPATH%\SvnVersion.tmp"
SubWcRev "%TRUNKPATH%\" "%TRUNKPATH%SvnVersion.tmp" "%TRUNKPATH%SvnVersion.cs" -f
IF ERRORLEVEL 1 GOTO ERROR
DEL "%TRUNKPATH%SvnVersion.tmp"
If you don't use TortoiseSVN, there are other ways to get this info in the file.
You will also need to remove this same information from your AssemblyInfo.cs files or you'll get a compile error. Also, to speed up Debug builds, this is only executed in Release builds (and in Debug builds only if the file doesn't initially exists, like after a fresh checkout).
I am desperately trying to deploy an ActiveX for IE developed in C# as a CAB archive. I have read many resources (some of them from StackOverflow) and it appears a lot of people are having the same problems. I have tried 3 solutions: a) creating a CAB VS project, b) manually creating a CAB using CABARC with a COM registration in INF and c) manually creating a CAB with launching msiexec. None of them worked. I even tried d) creating a bootstrapper which launches msiexec to no avail (because some people suggested simply launching msiexec on Vista can't work).
I am running Windows Vista but my project fails to run even on IE6 on XP.
When I install ActiveX using MSI, all is fine on ALL Windows. Apparently CAB thing is not working and I could not find a proper way to debug this whole process yet.
Any help is appreciated.
Update: Note that this old but excellent answer is still a very good outline for how to approach solving this problem, at least as along the evolutionary scale as Win7 and IE11. I just succeeded making it all work using the Answerer's Firebreath.org toolset as a jumping off point. It's not simple but it can be done. I've added a reference to that project to the reference list below since it may make a more logical jumping off point for current developers than this overview is.
Hooray - I have just finished an identical project, so you'll be pleased to know that it's actually possible. I have only tested this on XP - I understand there may be issues where Vista/7 don't allow msiexec to be called.
Given that you have an assembly correctly exposing a COM interface, I did the following:
Strong-named the assembly.
Created an INF file
Created an MSI using the Visual Studio 2008 "Setup Project" template.
Created a CAB file using "iexpress.exe" bundled with Windows XP.
Create INF file
The *.inf file I used looks like:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
install=install
[install]
run=msiexec.exe /package """%EXTRACT_DIR%\SampInst.msi""" /qn
The only bit you should need to change is the SampInst.msi. Note I would use an 8.3 filename, as long filenames can cause issues. While testing, I would not use the qn switch either, as that is a silent install.
Create the Installer
The installer has to do only one thing, and that is register the assembly by calling RegAsm on it. Most installers will provide some method to easily do this. For example, an installer created through VS 2008 will simply need to have the “Register” property of the assembly set to “vsdrpCOM”. Note that vsdrpCOM should be chosen as it generates the appropriate registry entries at build-time. The vsdrpCOMSelfRegistration setting is likely to fail as it calls RegAsm at run-time, and will thus not work for non-administrators.
Package the installer into a CAB file
This can be done by any cab archiver. Windows XP contains iexpress.exe, a wizard driven archiver, while Microsoft’s CAB SDK contains cabarc.exe. Other 3rd-party tools are also available.
Note that you will need to reserve space in the CAB file for code-signing if you are going to sign the CAB.
You will need to CAB the INF file, and the MSI file. You will not need to CAB the Setup.Exe file.
Handy hint: The VS2008 Setup Project project type allows you to set a post-build step in the properties, so you can build and CAB in a single step. My post-build step looks like:
cd "$(ProjectDir)"
"%WINDIR%\System32\Makecab.exe" /f "VboCslib.ddf"
The DDF file format is documented.
Sample HTML page
The object tag is used to point to the cab file containing the installer. A very simple HTML page which would deploy an ActiveXControl would be:
<html>
<head></head>
<body>
<!--
ID : The id of the ActiveX control to be used in JavaScript.
CLASSID : The GUID associated with the ActiveX control.
CODEBASE: The location containing the CAB installer for the ActiveX
control. This could be a URL, or a relative path.
-->
<OBJECT ID="MyActiveXControl"
CLASSID="CLSID:FC36FAE1-48E0-4f6b-B469-E1B5A8C6D1AC"
CODEBASE="cabfiles\SampleCabFile.CAB#version=1,0,0,0">
</OBJECT>
<script>
MyActiveXControl.SomeMethod();
</script>
</body>
</html>
Handy hints
Ensure your installer installs on a "per-user" basis, not a "per-machine" basis. This will make it more likely to install if the user does not have admin privileges.
Trouble-shooting
Internet Explorer 6 actually provides a really useful diagnostic aid. Clear your Temporary Internet Files, then navigate to the web-page. If the installation does not work, go to your temporary internet files and you will see a couple of files in there. One of these will be an error log starting ?CodeDownloadErrorLog. Drag it to your desktop and open it in notepad, and it will give details on what it was trying to do when it failed.
References
Microsoft KB247257 – Steps for signing a .cab file
MSDN – About INF File Architecture
SN.EXE - Code Strong Programs with Strong Names
Nikolkos Craft – How To: Deploy .NET ActiveX Control
CodeProject – Create ActiveX .NET Step by Step
CodeProject – Downloading C# ActiveX Components through CAB file
MSDN - ALLUSERS Property (Windows)
MSDN – Non-Admin ActiveX Controls
MSDN – Microsoft Cabinet Format
Update: Firebreath.org has a toolset for generating browser plugins for many platforms. The IE/ActiveX code to solve the problem posed here is just a subset. But as of 6 Nov 2014, I found it easier to start with Firebreath and its instructions than to try to build up my dev environment and roll all my own solutions from scratch.
My company is having trouble figuring out the best way to manage our builds, releases, and branches... Our basic setup is we have 4 applications we maintain 2 WPF applications and 2 ASP.NET applications, all 4 of these applications share common libraries, so currently they are all in one folder /trunk/{app1, app2, app3, app4}.
This makes it very hard to branch/tag a single application because you are branching all 4 at the same time, so we would like to separate it out into something like {app1,app2,app3,app4}/{trunk,tags,branches} but then we run into the issue of where to put the shared libraries?
We can't put the shared libraries as SVN externals because then when you branch/tag the branch is still referencing the trunk shared libs instead of having them branched as well.
Any tips? Ideas?
We are currently using svn and cruisecontrol.net.
EDIT: The shared libraries are changing often as of right now, which is why we can't use them as svn externals to trunk, because we might be changing them in the branch. So we can't use them as binary references.
Its also very hard to test and debug when the libraries are statically built instead of including the source.
I guess it all depends on how stable the shared libraries are. My preference would be for the shared libraries to be treated as their own project, built in CruiseControl like the others. Then the four main applications would have binary references to the shared libraries.
The primary advantage with this approach is the stability of the applications now that the shared libraries are static. A change to the libraries wouldn't affect the applications until they explicitly updated the binaries to the newer version. Branching brings the binary references with it. You won't have the situation where a seemingly innocuous change breaks the other three applications.
Can you clarify why you don't like branching all four applications at the same time?
This makes it very hard to branch/tag a single application because you are branching all 4 at the same time
I usually put all my projects directly under trunk as you are currently doing. Then when I create a release branch or a feature branch, I just ignore the other projects that get carried along. Remember, the copies are cheap, so they're not taking up space on your server.
To be specific, here's how I would lay out the source tree you've described:
trunk
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
branches
WPF1 v 1.0
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
WPF1 v 1.1
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
lib1 payment plan
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
We are kicking off an open source project to try and deal with this issue. If anyone is interested in commenting on it or contributing to it, it's at:
http://refix.codeplex.com
I agree with #Brian Frantz. There's no reason to not treat the shared libraries as their own project that is built daily and your projects take binary dependency on the daily builds.
But even if you want to keep them as a source dependency and build them with the app, why wouldn't the SVN externals approach work for you? When you branch particular app, there's no need to branch the shared library as well, unless you need a separate copy of it for that branch. But that means, it not a shared library anymore, right?
I've tried solving this problem several ways over the years, and I can honestly say there is no best solution.
My team is currently in a huge development phase and everyone basically needs to be working off of the latest and greatest of the shared libs at any given time. This being the case we have a folder on everyone's C: drive called SharedLibs\Latest that is automatically synced up with the latest development release of each of our shared libraries. Every project that should be drinking from the firehose has absolute file references to this folder. As people push out new versions of the shared libs, the individual projects end up picking them up transparently.
In addition to the latest folder, we have a SharedLibs\Releases folder which has a hierarchy of folders named for each version of each shared lib. As projects mature and get towards release candidate phase, the shared lib references are pointed to these stable folders.
The biggest downside to this is that this structure needs to be in place for any project to build. If someone wants to build an app 10 years from now, they will need this structure. It is important to note that these folders need to exist on the build/CI server as well.
Previous to doing this, each solution had a lib folder that was under source control containing the binaries. Each project owner was tasked with propagating new shared dlls. Since most people owned several projects, things often fell through the cracks for the projects that were still in the non-stable phase. Additionally TFS didn't seem to track changes to binary files that well. If TFS was better at tracking dlls we probably would have used a shared libs solution / project instead of the file system approach we are taking now.
Apache NPanday + Apache Maven Release
... might solve your problems
It gives you dependeny management (transitive resolving), strong versioning support, and automatic tagging/branching on 14+ version control systems, including SVN.
Give me a hint, if I should elaborate more.
I think there is no way you can avoid versioning and distributing your shared libs as separate artifacts, but Maven helps you alot doing that!
And you can allways do tricks to get it all opened in one Solution :-)
A sample workflow:
Dev 1 build A locally using Maven
Checks in sources
Build server builds A and deploys so-called SNAPSHOT-Versions to Repository Manager (e.g. Nexus)
Dev 2 two loads B, NPanday will automatically resolve the A-libs from the Repository Manager (No need to get the source and build)
Dev 1 wants to release A: Maven Release creates a branch or a tag with your source, finalizes the Version (removing SNAPSHOT) and deploys the artifacts to a Repository Manager.
Dev 2 can now upgrade B to use the final release of A (change entry in xml, or use VS-addin to do so)
Now Dev 2 can release B, again with automatic creation of tag or branch and deployment of built artifacts.
If you want to provide zipped packages as output from your build, Maven Assembly Plugin will help you do that.
You can use Apache/ IVY in standalone mode.
http://ant.apache.org/ivy/history/latest-milestone/standalone.html
I need to emphasize "stand alone" mode. If you google for examples....you will find alot of (not standalone) ones.
Basically, IVY works on this premise.
You publish binaries (or any kind of file, but I'll say binaries from this point forward).....as little binary-packages.
Below is PSEUDO code, do not rely on my memory.
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.4 (<< where the .xml refers to N number of files that make up the one package.))
"Package" simply means a group of files. You can include .dll and .xml and .pdb files in a package (what I do with a DotNet build of assemblies). Or whatever. IVY is file-type agnostic. If you want to put WordDocs up there you could, but sharepoint is better for documents.
As you make bug fixes to your code, you increment the revision.
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.5
then later you can retrieve from IVY what you want.
java.exe ivy.jar -retrieve PackagesINeed.xml
PackagesINeed.xml would contain information about the packages you want.
something like
"I want version '1.2+ of the MyBinaryPackageOne"
(defined in xml)
As you build your framework binaries...you PUBLISH to IVY.
Then, as you develop and build your code...you RETRIEVE from IVY.
In a NUTSHELL, IVY is a repository for FILES (not source code).
Ivy then becomes the definitive source of your binaries.
None of the "Hey, Developer-Joe has the binaries we need" kind of bull-mess.
.......
Advantages:
1. You do NOT keep your binaries in source control. (and thus do not BLOAT your source control).
2. You have ONE definitive source for binaries.
3. Through xml configuration, you say which versions you need for a library.
(In the example above, if version 2 (2.0.0.0) of MyBinaryPackageOne is published to IVY (let's assume with breaking changes from 1.2.x.y)...then you are OK, because you defined in your retrieve (xml configuration file) .. .that you only want "1.2+". Thus your project will ignore anything 2+...unless you change the configuration package.
Advanced:
If you have a build machine (CruiseControl.NET for example)....you can write logic to publish your (newly built) binaries to IVY after each build.
(Which is what I do).
I use the SVN revision as the last number in the build number.
If my SVN revision was "3333", then I would run something like this:
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.3333
Thus whenever retrieve the package for revision "1.2.3+" .... I'll get the latest build.
In this case, I would get version 1.2.3.3333 of the package.
It's sad that IVY was started in 2005 (well, that's the good news)...but that NUGET didn't come out til 2010? (2011?)
Microsoft was 5-6 years behind on this one, IMHO.
I would never go back to putting binaries in source control.
IVY is very good. It is time proven. It solves the problem of DEPENDENCY management.
Does it take a little bit of time to get comfortable with it?
Yep.
But it is worth it in the end.
My 2 cents.
.................
But idea #2 is
Learn how to use NUGET with a local (as in..local to your company) repository.
That is the about the same thing as IVY.
But having looked at NUGET, I still like IVY.