I have a custom action that shows list of application pools in the system and want to bind these values into combobox which is inside customdlg.wxs and while executing MSI setup I should get a combobox that show list of app pools.
Can anyone guide me how to bind values to combobox?
custom action
//List all App pools
public static ActionResult GetAppPools(Session session)
{
using (ServerManager iisMgr=new ServerManager())
{
System.Collections.IEnumerator ie = iisMgr.ApplicationPools.GetEnumerator();
List<string> apppools = new List<string>();
while (ie.MoveNext())
{
apppools.Add(((Microsoft.Web.Administration.ApplicationPool)(ie.Current)).Name);
}
}
return ActionResult.Success;
}
customdlg.wxs
<Control Id="ApplicationPoolLabel" Type="Text" Y="94" X="11" Width="349" Height="16" TabSkip="no" Text="Application Pool: " />
<Control Id="ApplicationPoolCombo" Type="ComboBox" Y="94" X="100" Width="150" Height="16" ToolTip="Application Pool" Property="APP_POOL" Text="{80}">
<ComboBox Property="APP_POOL">
<ListItem Text="[APP_POOL]" Value="[APP_POOL]" />
</ComboBox>
</Control>
Related
i need to creata a app with support multilingual.
So i did a sample app like below.
Page.xamal
<StackLayout
VerticalOptions="CenterAndExpand">
<Label Text="{x:Static local:AppResources.Title}" TextColor="Black"
HorizontalOptions="CenterAndExpand" />
<Button Text="{x:Static local:AppResources.ClickMe}" Clicked="Button1_Clicked"/>
<Label Text="{x:Static local:AppResources.Title}" TextColor="Black"
HorizontalOptions="CenterAndExpand" />
<Button Text="{x:Static local:AppResources.ClickMe}" Clicked="Button2_Clicked"/>
</StackLayout>
page.xamal.cs
private void Button1_Clicked(object sender, EventArgs e)
{
CultureInfo culture = new CultureInfo("th");
AppResources.Culture = culture;
}
as xmarin forms documentation provide i set the AssemblyInfo.cs (Common folder)
[assembly: NeutralResourcesLanguage("en-GB")]
so my default language is "en-GB".
i have 3 AppRerources.resx
AppResources.resx
AppResources.th.resx
AppResources.en-GB.resx
but when i press first button i could not see that app is changing the language.
anything i missed here?
About changing current cultureinfo, I suggest you can try to use Plugin.Multilingual to get it.
firstly, installing Plugin.Multilingual by nuget package, define .resx file like this:
In TranslateExtension.cs file in the constant ResourceId by default it will assume your resource file is added in the root of the project and the resx file is named as AppResources. If you added it to a folder or named the resx file differently you can change it there.
public class TranslateExtension : IMarkupExtension
{
const string ResourceId = "MultilingualSample.AppResources";
static readonly Lazy<ResourceManager> resmgr = new Lazy<ResourceManager>(() => new ResourceManager(ResourceId, typeof(TranslateExtension).GetTypeInfo().Assembly));
public string Text { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return "";
var ci = CrossMultilingual.Current.CurrentCultureInfo;
var translation = resmgr.Value.GetString(Text, ci);
if (translation == null)
{
#if DEBUG
throw new ArgumentException(
String.Format("Key '{0}' was not found in resources '{1}' for culture '{2}'.", Text, ResourceId, ci.Name),
"Text");
#else
translation = Text; // returns the key, which GETS DISPLAYED TO THE USER
#endif
}
return translation;
}
}
More detailed info, please take a look:
https://github.com/CrossGeeks/MultilingualPlugin
Pass argument in CultureInfo the culture you want to set , e.g. I set it to German in my example
CultureInfo ci = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
I am using Windows.Storage GetFilesAsync function to retrieve file information, but am finding that the file count is often incorrect (compared to OS properties). Strangely sometimes the number is smaller and other times larger than the OS count!?
I've created a mini project to replicate the issue. On folders with very small file count, they do match, but with larger counts (i.e. 500+) the count is often way off.
To replicate create a Universal Windows blank app, then copy this to MainPage.xaml:
<Page
x:Class="TestFileCount.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestFileCount"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Button Name="btnSelect" Content="Select Folder" HorizontalAlignment="Left" Height="195" Margin="254,412,0,0" VerticalAlignment="Top" Width="805" Click="btnSelect_Click"/>
<TextBlock Name="txtFolder" HorizontalAlignment="Left" Height="92" Margin="185,212,0,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" Width="1156"/>
<TextBlock Name="txtResult" HorizontalAlignment="Left" Height="163" Margin="96,701,0,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" Width="1210"/>
</Grid>
Finally copy this to MainPage.xaml.cs and run the app:
using System;
using System.Collections.Generic;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Search;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace TestFileCount
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void btnSelect_Click(object sender, RoutedEventArgs e)
{
const string SizeProperty = "System.Size";
const string DateModProperty = "System.DateModified";
var folderPicker = new Windows.Storage.Pickers.FolderPicker
{
SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop
};
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
//cancelled
if (folder == null)
{
return;
}
txtResult.Text = "Processing...";
txtFolder.Text = folder.Path;
btnSelect.IsEnabled = false;
// Set up file settings
List<string> fileTypeFilter = new List<string>();
List<string> propertyNames = new List<string>
{
SizeProperty,
DateModProperty
};
// Create query options
QueryOptions queryOptions = new QueryOptions(CommonFileQuery.OrderByName, fileTypeFilter)
{
FolderDepth = FolderDepth.Deep,
IndexerOption = IndexerOption.UseIndexerWhenAvailable
};
queryOptions.SetPropertyPrefetch(PropertyPrefetchOptions.BasicProperties, propertyNames);
StorageFileQueryResult query = folder.CreateFileQueryWithOptions(queryOptions);
//get files
IReadOnlyList<StorageFile> fileList = await query.GetFilesAsync();
txtResult.Text = fileList.Count.ToString();
btnSelect.IsEnabled = true;
}
}
}
It seem to be a known issue and it does not work because of OrderByName. Delete OrderByName.
QueryOptions queryOptions = new QueryOptions(){...};
It's mentioned here that it does not work outside of the library folder contrary to the documentation which states that it works everywhere.
Even though I tested it on my PC and it worked fine.
I am developing an installation msi file using Wix toolset (in VS 2012) and faced with the problem that I can't add a confirmation dialog when user press button 'Cancel'. I tried to add also custom action dll with the message box, but if the function returns ActionResult.Failure, then my setup shows error dialog.
Original control:
<Control Type="PushButton" Id="progressCancelBtn" Width="56" Height="17" X="296" Y="244">
<Text>Cancel</Text>
<Publish Event="EndDialog" Value="Exit" />
</Control>
Try number 1:
public class CustomActions
{
[CustomAction]
public static ActionResult ShowExitMessageBox(Session session)
{
DialogResult result = MessageBox.Show("Exit installation?", "Exit", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
return ActionResult.Failure;
}
else
{
return ActionResult.Success;
}
}
}
Custom action:
<CustomAction Id='ShowExitMsgBox' BinaryKey='CustomActions' DllEntry='ShowExitMessageBox' Execute='immediate' Return='ignore'/>
<Binary Id='CustomActions' SourceFile='$(var.CASourcesPath)\CustomActions.CA.dll'/>
And tried to use:
<Control Type="PushButton" Id="cancelBtn" Width="56" Height="17" X="300" Y="244" Cancel="yes">
<Text>Cancel</Text>
<Publish Event="DoAction" Value="ShowExitMsgBox">1</Publish>
<!--Publish Event="EndDialog" Value="Exit" /-->
</Control>
But it shows like failure, instead of cancellation.
Thank you for help in advance.
Update:
I changed my custom action C# code to the next:
public class CustomActions
{
[CustomAction]
public static ActionResult ShowExitMessageBox(Session session)
{
DialogResult result = MessageBox.Show("Exit installation?", "Exit", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
session["CANCELEDPROP"] = "1";
}
else
{
session["CANCELEDPROP"] = "0";
}
return ActionResult.Success;
}
}
and WIX part:
// in Product.wxs
<Property Id="CANCELEDPROP" Secure="yes">0</Property>
// in UIFile.wxs
<Control Type="PushButton" Id="cancelBtn" Width="56" Height="17" X="300" Y="244" Cancel="yes">
<Text>Cancel</Text>
<Publish Event="DoAction" Value="ShowExitMsgBox">1</Publish>
<Publish Event="EndDialog" Value="Exit">CANCELEDPROP=1</Publish>
</Control>
It works on the first page, but I get an error on progress page: "Windows installer has stopped working" after I pressed some button on my message box. :(
I have found out if I don't use message box, then everything works. It is strange.
Update 2:
I tried to use session.Message instead of Windows.Forms, but message box just doesn't appear. Strange.
[CustomAction]
public static ActionResult ShowExitMessageBox(Session session)
{
Record record = new Record();
record.FormatString = "Exit installation?";
MessageResult result = session.Message(InstallMessage.Warning
| (InstallMessage)System.Windows.Forms.MessageBoxIcon.Warning
| (InstallMessage)System.Windows.Forms.MessageBoxButtons.YesNo,
record);
if (result == MessageResult.Yes)
{
session["CANCELEDPROP"] = "1";
}
else
{
session["CANCELEDPROP"] = "0";
}
return ActionResult.Success;
}
Finally I have found a solution by using CancelDlg from WixUIExtension.dll
(http://wixtoolset.org/documentation/manual/v3/wixui/dialog_reference/wixui_dialogs.html)
Add reference to WixUIExtension.dll (path on my computer is the next C:\Program Files (x86)\WiX Toolset v3.11\bin)
Add reference to icon that would be on the message box (Product.wxs):
< Binary Id="WixUI_Ico_Info" SourceFile="Images/MyIcon.ico" />
Control itself:
< Control Type="PushButton" Id="cancelBtn" Width="56" Height="17" X="300" Y="244" Cancel="yes">
< Text>Cancel
< Publish Event="SpawnDialog" Value="CancelDlg">1
< /Control>
How can I author a WiX custom action that
Is always called at the end of an installation, at least if there's an install error
Copies the current MSI log file from its current local to the user's APPDATA folder
I have this managed custom action code. Not sure how to author its invocation in my Wix script. Should the custom action be scheduled for after InstallFinalize? Can it be scheduled OnExit="error"?
[CustomAction]
public static void CopyLogFile(Session session)
{
const string company = "MyCompany";
const string product = "MyProduct";
try
{
session.Log("CustomAction.CopyLogFile entry");
var msiLogFilePath = session.CustomActionData["LOGFILEPATH"];
if (msiLogFilePath != null)
{
session.Log("CustomAction.CopyLogFile MSI log filename: {0}", msiLogFilePath);
var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var destDirPath = Path.Combine(localAppDataPath, company, product);
var destDir = Directory.CreateDirectory(destDirPath);
session.Log("CustomAction.CopyLogFile Destination directory: {0}", destDir.FullName);
var destFilePath = Path.Combine(destDir.FullName, Path.GetFileName(msiLogFilePath));
File.Copy(msiLogFilePath, destFilePath, true);
session.Log("CustomAction.CopyLogFile Log file copied to: {0}", destFilePath);
}
else
{
session.Log("CustomAction.CopyLogFile File path not found");
}
}
catch (Exception exception)
{
session.Log("CustomAction.CopyLogFile exception {0}", exception);
}
finally
{
if (session != null)
{
session.Log("CustomAction.CopyLogFile exit");
session.Close();
}
}
}
Yes, you can schedule it after InstallFinalize (so did I, but I copy it every time if it is not a complete removal of the package):
<InstallExecuteSequence>
<Custom Action="CopyLogfile" After="InstallFinalize">NOT (REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE)</Custom>
</InstallExecuteSequence>
Remember to also add it to the UI sequence if you have any. I added it as event to the PushButton in the SetupCompleteSuccess- and SetupCompleteError-dialogs (maybe you need to add it only to the latter one?) like in the following:
<Dialog Id="SetupCompleteSuccess" X="50" Y="50" Width="374" Height="266" Title="[ProductName]" NoMinimize="yes">
<Control Id="OK" Type="PushButton" X="230" Y="243" Width="66" Height="17" Text="&Finish" TabSkip="no" Default="yes" Cancel="yes">
<Publish Event="EndDialog" Value="Exit">1</Publish>
<!-- ### Invoking copying the logfile if the Finish-button is pressed -->
<Publish Event="DoAction" Value="CopyLogfile">MsiLogFileLocation AND NOT (REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE)</Publish>
</Control>
<!-- ... rest of the dialog ... -->
</Dialog>
Regarding showing it only in case of an error: Maybe checking for the ProductState-properrty? Searched the web for this but didn't find anything useful.
Edit: Maybe a proper way to execute it only in case of an error is the usage of Custom Action flags that execute it only during rollback. In WiX it would be the Execute="rollback"-attribute for the CustomAction-tag.
Don't mess with custom actions after InstallFinalize if you can help it. They are often skipped entirely when deploying via tools such as SCCM, Unicenter, etc...
A custom dialog with a button to open the log file at the end of the install could work ok though.
I am creating a MSI based Installer using Wix.
My Custom Action declaration goes like this...
<Binary Id="CustomActions" SourceFile="DLLs\CustomActions.CA.dll" />
<CustomAction Id="CheckPath" Return="check" Execute="immediate" BinaryKey="CustomActions" DllEntry="CheckPath" />
And under WixUI_InstallDir Dialog UI,
<UI Id="WixUI_InstallDir">
.....
<Publish Dialog="SelectDirDlg" Control="Next" Event="DoAction" Value="CheckPath" Order="2">1</Publish>
.....
</UI>
And in C# file,
[CustomAction]
public static ActionResult CheckPath(Session session)
{
Record record2 = new Record();
record.FormatString = "The path that you have selected is invalid!";
session.Message(InstallMessage.Error | (InstallMessage)MessageButtons.OK, record);
return ActionResult.Success;
}
I am expecting a Message box via the above Custom Action when the user selects an invalid path. But the message box is not shown.
What am I doing wrong?
Custom actions triggered via a DoAction control event cannot show message boxes. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa368322%28v=vs.85%29.aspx.