Say I want my programs to work correctly on anyone's computer in the world.
I have no clue how much work this takes but I figure it's easier to get right with a console app so I started by decompiling MSTest.exe entry point and found:
private static void SetUICulture()
{
Thread.CurrentThread.CurrentUICulture =
CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
if (
(
(Console.OutputEncoding.CodePage != 0xfde9) &&
(Console.OutputEncoding.CodePage !=
Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage)
) &&
(Console.OutputEncoding.CodePage !=
Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage)
)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
}
It looks like the intention here to look at the "fallback" culture, and then look at some conditions that would prevent it from being "good enough" and if so set it to us english.
What is is the 0xfde9 doing?
Does this effectively internationalize a console app?
The 0xfde9 code page is UTF-8. So the code says, if the code page is not UTF8, OEM, or ANSI, then set the culture to US English.
Now, your application should work correctly assuming the presence of the version of the .Net Framework your application requires, but the issue is whether or not the end user will be able to understand what your application is trying to tell them.
Related
So the title says it all, I would like C# code (so please, PLEASE make sure it isn't Visual Basic code). And that is all I want to ask. I have tried the web browser built in to the .NET framework, but it looks like some old version of IE (if I am right or not). And if you answered, well thanks I guess! I need this for a small project where a bot would just log on to a website (its a base for future projects).
By default it's IE7. You can bang a registry entry in to make it later:
public static void EnsureBrowserEmulationEnabled(string exename = "YourAppName.exe", bool uninstall = false)
{
try
{
using (
var rk = Registry.CurrentUser.OpenSubKey(
#"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", true)
)
{
if (!uninstall)
{
dynamic value = rk.GetValue(exename);
if (value == null)
rk.SetValue(exename, (uint)11001, RegistryValueKind.DWord);
}
else
rk.DeleteValue(exename);
}
}
catch
{
}
}
Code courtesy of this blog
The values you can use in place of 11001 can be found in MSDN
Alternatively; can you do what you want by using WebClient/HttpWebRequest rather than poking at a web browser control to navigate around? Or can you find some web service/api version of the site that will respond with JSON rather than trying to manipulate html?
I was mildly curious why you'd care what a page looks like if it's a bot that is using it, but perhaps you're hitting a "your IE is too old" from the server..
Vmware's .net api reference is somewhat confusing and hard to follow. I have been able to connect to my vcenter host then get a list of esxi hosts. Then I have been able get all the running modules on the host using HostKernelModuleSystem, and probe the properties on the variable "mod"... but I am not able to figure out how to get license info, I tried creating an object lic below, trying all different kinds of "types" from vmware with the word license in the type. but, it never works it has a problem converting the line with LicenseManagerLicenseInfo lic = .... I always get the following:
"Cannot convert type 'Vmware.Vim.Viewbase' to
'Vmware.Vim.LicenseManagerLicenseInfo'"
but the declaration above it for "mod" works fine.
I have also tried:
HostLicenseConnectInfo
LicenseAssignmentManagerLicenseAssignment
LicenseManager
I am hoping someone who has worked with vmware .net api can shed some light on what i am doing wrong? I am new to C# about 1 year :) but these VMware APIs are somewhat confusing to me.
esxList = client.FindEntityViews(typeof(HostSystem), null, null, null);
foreach (HostSystem host in esxList)
{
HostKernelModuleSystem mod = (HostKernelModuleSystem)client.GetView(host.ConfigManager.KernelModuleSystem, null);
LicenseManagerLicenseInfo lic = (LicenseManagerLicenseInfo)client.GetView(host.ConfigManager.LicenseManager, null);
string name = lic.Name;
}
I'll have to go to work tomorrow to look at this ( don't have ESX and VMWare SDK for .NET at home ) but I've done a bit of this work.
I wrote a generics method that wraps FindEntityViews and takes a filter as an argument. That makes it easy to search for anything. Also I've noticed that searches come back as ManagedObjectReferences and can't be cast to the subclasses. You have to construct them passing the ManagedObjectReference as an argument.
Also I find searching for PowerCLI examples and watching the classes in the immeadiate window very help in navigating this API. It's a fairly decent SDK but they put all of the classes in a single namespace and there's lots of little style inconsistencies ( Device instead of Devices and properties that take strings instead of enums when an enum exists ).
i figured out how to do it :) , by using http://vcenter_hostname/mob I was able to walk through api better. here is what I did, plus instead of of using "host" which was type HostSystem I jused my instance of my vCenter host "client"
VMware.Vim.LicenseManager lic_manager = (VMware.Vim.LicenseManager)client.GetView(client.ServiceContent.LicenseManager, null);
LicenseManagerLicenseInfo[] lic_found = lic_manager.Licenses;
foreach (LicenseManagerLicenseInfo lic in lic_found)
{
string test = lic.Name.ToString();
string test2 = lic.LicenseKey.ToString();
}
I have setup a windows forms project to use localization so that it will support Chinese and English languages. I have built in a way of forcing the language to one or the other when the form loads. Before InitializeComponent() is called I have a bit of code that does this...
switch (Properties.Settings.Default.SelectedLanguage)
{
case "":
break;
case "English":
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
break;
case "Chinese":
try
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CHT");
Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CHT");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
break;
}
So when the SelectedLanguage property is set to "Chinese" the program should use the Chinese localization right? I tested this while debugging and it worked exactly as expected. That is, when SelectedLanguage == "Chinese" at the program start all the buttons and labels display in the Chinese text that I entered. When the SelectedLangugage == "English" everything is displayed in the English Text that I have entered.
The problem is that when I install this program and run it (not debugging) it doesn't work. Even on my development machine. No matter what SelectedLanguage is set to the program always displays the English Localization. I even put in a message box to pop up at the beginning of the program which displays `Application.CurrentCulture.Name' and it shows the Chinese culture name (zh-CHT) but it still displays everything in English. So what is the difference between what happens during debugging and during actual run time? And how can i fix it?!?
Make sure that your localized resources Dll are correctly installed.
Your installer should put resources files into sub-folders such as
zh-CHT\AssemblyName.resources.dll
It sounds like the english default is being used at all times, which would suggest that the resources you have set up for Chinese are not being included in the build. Double check your resources and make sure it is included in your deployment.
I've been working on a pet project on the weekends to learn more about C# and have encountered an odd problem when working with localization. To be more specific, the problem I have is with System.Threading.Thread.CurrentThread.CurrentUICulture.
I've set up my app so that the user can quickly change the language of the app by clicking a menu item. The menu item in turn, saves the two-letter code for the language (e.g. "en", "fr", etc.) in a user setting called 'Language' and then restarts the application.
Properties.Settings.Default.Language = "en";
Properties.Settings.Default.Save();
Application.Restart();
When the application is started up, the first line of code in the Form's constructor (even before InitializeComponent()) fetches the Language string from the settings and sets the CurrentUICulture like so:
public Form1()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language);
InitializeComponent();
}
The thing is, this doesn't work consistently. Sometimes, all works well and the application loads the correct language based on the string saved in the settings file. Other times, it doesn't, and the language remains the same after the application is restarted.
At first I thought that I didn't save the language before restarting the application but that is definitely not the case. When the correct language fails to load, if I were to close the application and run it again, the correct language would come up correctly. So this implies that the Language string has been saved but the CurrentUICulture assignment in my form constructor is having no effect sometimes.
Any help? Is there something I'm missing of how threading works in C#? This could be machine-specific, so if it makes any difference I'm using Pentium Dual-Core CPU.
UPDATE
Vlad asked me to check what the CurrentThread's CurrentUICulture is. So I added a MessageBox on my constructor to tell me what the CurrentUICulture two-letter code is as well as the value of my Language user string.
MessageBox.Show(string.Format("Current Language: {0}\nCurrent UI Culture: {1}", Properties.Settings.Default.Language, Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName));
When the wrong language is loaded, both the Language string and CurrentUICulture have the wrong language. So I guess the CurrentUICulture has been cleared and my problem is actually with the Language Setting.
So I guess the problem is that my application sometimes loads the previously saved language string rather than the last saved language string. If the app is restarted, it will then load the actual saved language string.
I got the same problem. I figured out that Application.Restart() do not really make an absolutely restart, see MSDN.
So Application.Restart() do not call the initializing things within the forms constructor
like InitializeComponent(), more the "Applications are restarted in the context in which they were initially run."
So your code is correct
Properties.Settings.Default.Language = "en";
Properties.Settings.Default.Save();
public Form1()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language);
//...
InitializeComponent();
}
but it doesn't work this way with Application.Restart(). If You close the app and open it again your (new) settings are taken.
So we have to find a way to initialize the form again to make the new language settings happen.
Could you check what is your thread's CurrentUICulture?
I remember having a problem like yours; it was solved by reloading the resource dictionary containing the strings to be localized:
Thread.CurrentThread.CurrentUICulture = <new culture>;
ResourceDictionary newDict = new ResourceDictionary();
newDict.Source = localizedStrings.Source;
localizedStrings = newDict;
(and this approach worked dynamically as well; here is some more information).
You could manually change the language of the current form similar to this:
CultureInfo cInfo = new CultureInfo("en-US");
ResourceManager rm = new ResourceManager(GetType());
// For each control on the form, perform the translation manually (probably better in a loop)
control1.Text = rm.GetString(control1.Name + ".Text", cInfo);
// Now set the culture for all other dialogs
Thread.CurrentThread.CurrentUICulture = cInfo;
Hope that helps!
You could simply "reset" your application by closing the open forms and re-creating them. Then you could directly set the culture when the user changes the setting.
Also, try giving some debug output so you see what values are being set and if the culture is actually what you expect.
EDIT: My guess: Since the data has to be written to a file, and then loaded from that file, you may be restarting too quickly for the write to have been completed.
By using CurrentThread.CurrentUICulture, and then changing the form, you don't need to restart the application. Ref my old post here
C# VS 2005.
I have developed an application that run perfectly on my development machine when I install it. However, it doesn't run on any of the clients machines.
I have tested with VMWare with a fresh install of windows, and still the application doesn't run.
I have added logging to try and determine where the application is failing. My previous versions worked, and after a week of development I gave to the client and then experienced this problem.
I have entered logging at the start and end of the constructor and form_load event. The constructor runs ok. However, at the end of the constructor it doesn't run in the form_load event as I have a log statement that should print out.
When the application runs it displays for a few seconds in task manager then fails to load.
I think this could be a very difficult problem to solve. So if anyone has experienced this before or could point me in the right direction to solve this problem.
The code in the form load event.
private void CATDialer_Load(object sender, EventArgs e)
{
my_logger.Info("Start of form load event"); // Doesn't display this.
.
.
}
===== Edit static main ====
[STAThread]
static void Main()
{
Application.SetCompatibleTextRenderingDefault(false);
// Get the language and set this cultureUI in the statusdisplay that will
// change the language for the whole program.
string language = CATWinSIP.Properties.Settings.Default.Language;
if (language == "th-TH")
{
StatusDisplay.StatusDisplay status_display = new StatusDisplay.StatusDisplay(true);
}
else if(language == "en-GB")
{
StatusDisplay.StatusDisplay status_display = new StatusDisplay.StatusDisplay(false);
}
try
{
Application.Run(new CATDialer());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
=== Constructor ===
public CATDialer()
{
//Set the language for all the controls on the form.
//Has to be done before all components are initialized.
//If not Thai language then must be using English.
if (Settings.Default.Language == "th-TH")
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("th-TH");
}
else
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
}
InitializeComponent();
this.statusDisplay1.BalanceStatus = CATWinSIP_MsgStrings.BalanceStatus;
this.statusDisplay1.RedialHistory = CATWinSIP_MsgStrings.RedialHistory;
this.statusDisplay1.LoginStatus = CATWinSIP_MsgStrings.LoginSuccessful;
// Enable logging
XmlConfigurator.Configure();
logger.Info("CATDialer Constructor(): XmlConfigurator.Configure() Loaded [ OK ]");
// MessageBox.Show("Balance Status: " + this.statusDisplay1.BalanceStatus);
//Short cut menu.
this.SetupShortCutMenu();
this.fill_properties();
logger.Debug("CATDialer Constructor(): Fill properties loaded [ OK ]");
}
--
Hello,
Thanks for all the advice.
I have problem with one of my class libraries I created that used a crypto stream.
I found the answer when I added this to my program.cs
The message box displayed the information for the failed assembly.
Thanks,
try
{
Application.Run(new CATDialer());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Have you checked on a different development machine? Are your systems running same version of the .net framework? Is the .net framework installed correctly on the remote system? Have you tested your application in a different environment?
edit: have you tried spamming your log? Wrap the entire thing in a try catch and see what you can capture. Sometimes I found using the messagebox useful for this kind of logging (MessageBox.Show())
You probably need to post a bit more detail about the type of exception that is being thrown to get the most help.
If all the obvious checks such as having the correct framework version pass, the next thing to fail can often be a missing assembly.
If this is the case you may want to troubleshoot assembly loading in your app.
The MS Assembly Binding Log Viewer (fuslogvw) is a valuable piece of kit for this task.
In this sort of scenario I frequently find .NET assembly binding log viewer (Fusion) very useful in finding out what is going on. With fusion you can see which assemblies are being loaded and where they are being loaded from. More importantly for you, it is possible to enable it so that fusion also displays the assemblies that fail to load and where .NET tried to load them from.
Check out the MSDN article on fusion if you think this might help.