I am using the following code snippet to launch a folder dialog.
BROWSEINFO bi;
ZeroMemory(&bi, sizeof(bi));
TCHAR szDisplayName[MAX_PATH];
szDisplayName[0] = 'a';
bi.hwndOwner = NULL;
bi.pidlRoot = NULL;
bi.pszDisplayName = szDisplayName;
bi.lpszTitle = _T("Please select a folder to locate your PGA :");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lParam = NULL;
bi.iImage = 0;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
TCHAR szPathName[MAX_PATH];
if (NULL != pidl)
{
BOOL bRet = SHGetPathFromIDList(pidl,szPathName);
if(FALSE == bRet)
{
return;
}
else
{
PGA_PATH.Clear();
PGA_PATH.SetWindowTextA(szPathName);//To set the user selected path to the text box
SetValudata(szPathName);//to save the user selected path to the file.
}
}
Now I want to restrict the user to restrict if user tries to select some specific folder (PGA).
For Example.
If user selected path=
C:\Users\mm232\Desktop\PGA
C:\Users\mm232\Pictures\PGA
C:\Users\mm232\\PGA\Pictures
then do not allow the user to select the path or disable the selection.
The folder browser dialog is slow because it may spin up CD drives and power up sleeping external hard drives. A good design would allow the user to type the path into a textbox, and then add a browsing button next to it. The validation is then done on the textbbox not in the folder browsing dialog.
That said you do have options to prevent users from selecting certain folder by passing a callback function in the lpfn member of the BROWSEINFO structure. The callback function can do the following:
Handle BFFM_IUNKNOWN and QI lparam for IFolderFilterSite. Call IFolderFilterSite::SetFilter with your own implementation of IFolderFilter that determines each folder's visibility.
Handle BFFM_SELCHANGED, check the pidl passed in lparam and send BFFM_ENABLEOK to enable/disable the OK button. Optionally, send BFFM_SETSTATUSTEXT to show the reason why a folder can not be selected.
Related
The goal:
What I want to do is drag a GridViewItem from a GridView in a UWP app outside of the app to the desktop explorer. During the drop event, I want to download a file from the internet and create a StorageFile that will be used to populate the DataPackage. I want this StorageFile to be copied to the desktop. Unfortunately, when a deferral is used for UWP Drag&Drop (using SetDataProvider), as soon as you leave the app window, the request is activated and you have to populate the DataPackage with the object to be transferred. So, it seemed to me that I would need to use a deferred type of StorageFile created with CreateStreamedFileFromUriAsyc.
I do not want to pre-download the data every time I start to do a drag and drop operation. I only want to download the data when I'm actually dropping it somewhere legitimate to copy.
I know how to drag and drop a pre-existing StorageFile from UWP to Explorer (desktop) using a deferred request.
I also know how to create a StorageFile using CreateStreamedFileFromUriAsyc that will gives you a StorageFile that downloads data only when the data is requested.
When I try to combine these two ideas, windows Explorer gives me the error 'interface is not supported.'.
If I use the exact same code, but just get the file contents by calling something like GetBasicPropertiesAsync during the deferred drag handler, it works only if I hold the drag over the desktop until the file is downloaded. I can see it finishing when the drag icon changes from the 'prohibited' icon to 'copy'. If I let go of the mouse button before it is done, no copy will occur and no errors are raised.
Obviously, I would like the drag and drop to download without having to manually start it on the deferred handler. Any ideas? Is this possible?
(Yes, I realize the code to create the correct file extension is wrong/incomplete, but that's irrelevant here...)
//DragStarted Handler in constructor
DragItemsStartedCommand = ReactiveCommand.Create<DragItemsStartingEventArgs>((e) =>
{
_dragItems = e.Items.Cast<ItemViewModel>();
e.Data.Properties.Title = "Transfer file";
e.Data.Properties.Description = "desscription of transfering a file";
e.Data.Properties.FileTypes.Add(StandardDataFormats.StorageItems);
e.Data.SetDataProvider(Windows.ApplicationModel.DataTransfer.StandardDataFormats.StorageItems, OnDeferredStorageFileRequestedHandler);
e.Data.RequestedOperation = DataPackageOperation.Copy;
});
//Deferred request handler
async void OnDeferredStorageFileRequestedHandler(DataProviderRequest request)
{
DataProviderDeferral deferral = request.GetDeferral();
try
{
Task<IEnumerable<StorageFile>> task = null;
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
task = DownloadStorageFiles();
});
var result = await task;
request.SetData(result);
}
catch (Exception ex)
{
// Handle the exception
}
finally
{
deferral.Complete();
Debug.WriteLine("deferral complete!!!");
}
}
//Create StorageFile with deferred loading Task
async Task<IEnumerable<StorageFile>> DownloadStorageFiles()
{
List<StorageFile> storageItems = new List<StorageFile>();
foreach (var item in _dragItems)
{
var request = new RestSharp.RestRequest();
var defaultItemType = ItemType.MSWord;
switch (item.MimeTypeTranslated)
{
case ItemType.GoogleDocument:
case ItemType.GoogleSpreadsheet:
case ItemType.GooglePresentation:
case ItemType.GoogleDrawing:
case ItemType.GoogleScript:
request.Resource = $"files/{item.File.id}/export";
request.AddParameter("mimeType", Statics.ItemTypeDictionary.First(x => x.Value == defaultItemType).Key);
break;
default:
request.Resource = $"files/{item.File.id}";
request.AddParameter("alt", "media");
break;
}
string fileName = "";
if (item.File.name.EndsWith($".{Statics.ItemExtensionDictionary[defaultItemType]}"))
fileName = $"{item.File.name}";
else
fileName = $"{item.File.name}.{Statics.ItemExtensionDictionary[defaultItemType]}";
var uri = account.Client.GetAuthorizedUriForDownload(request);
var thumbnail = RandomAccessStreamReference.CreateFromFile(await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///StoreLogo.png")));
var storageFileDeferred = await StorageFile.CreateStreamedFileFromUriAsync(fileName, uri , thumbnail);
//var props = await storageFileDeferred.GetBasicPropertiesAsync();
storageItems.Add(file);
}
return storageItems;
}
GitHub repro of this problem:
https://github.com/limefrogyank/DragDeferredFileToDesktop
First page is a regular drag to desktop that works because StorageFile (+ underlying data) is already in assets folder
Second page shows the error generated when using a StorageFile that is created with CreateStreamedFileFromUriAsync.
Third page uses the same type of StorageFile, but with a hack to force the retrieval of data synchronously. Desktop freezes for a second until data is ready.
As of the recent Windows updates the drag n' drop of storage files on UWP apps is automatically handled by the system.
example gif.
I am working on C# win from.I am created one user control which is holding the HTML type of information and displaying it in web browser control(web browser control placed in user control)all user control filled with information and display to the users as per requested(by date & time).
but i fixed the size(Height & width) of web browser. when information is larger then web browser it should show the scroll bar so user can scroll it.
this all user control i filed with information and placed in table panel.then table panel object reference is given to other table object (which is in another C# project). and then this table panel is added with panel control and display it.
Problem is that when size of user control's web browser control changed(I checked sized in Document Completed event and set the web browser.Scroll Bars Enabled = true;) the information which is holding by web browser will not displaying.
Following is my code
private void wbContainer_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if ((this.wbContainer.Document.Body.ScrollRectangle.Size.Height > this.wbContainer.Size.Height))
{
this.wbContainer.ScrollBarsEnabled = true;
this.wbContainer.Refresh();
}
}
User control is added in table panel
public TableLayoutPanel createInfoSection(string arg_startDateTime, string arg_endDateTime)
{
Control objControl = null;
int Rows = 3;
objTablePageNotes = new TableLayoutPanel();
// Initialized tableLayoutPanel property
objTablePageNotes = setTablePanelProperties(objTablePageNotes);
//returning the collection of html information
InformationCollection objInformationCollection = new InformationCollectionManager().GetInformationCollectionData(arg_startDateTime, arg_endDateTime);
if (objInformationCollection != null)
{
if (objInformationCollection.Count > 0)
{
foreach (InformationList objList in objInformationCollection)
{
//this will return control with filling the html information
objControl =ControlFactory.getControl("InfoTemplate",objList.HtmlInformation);
objControl.Dock = DockStyle.Fill;
objTablePageNotes.SetColumnSpan(objControl, 1);
objTablePageNotes.Controls.Add(objControl, 1, Rows);
objTablePageNotes.ResumeLayout(true);
objTablePageNotes.RowStyles.Clear();
objTablePageNotes.RowStyles.Add(new RowStyle(SizeType.AutoSize));
objTablePageNotes.RowCount = Rows;
Rows++;
}
}
}
return objTablePageNotes;
}
then this table panel object ref is assigned to
tbPanelNoteSection = new CanvasDesignHandler().createInfoSection(_STARTDATE, _ENDDATE);
finally it added to panel control
this.pnlPage.Controls.Add(tbPanelNoteSection);
I add in DocumentCompleted event :
if ((this.wbNoteContainer.Document.Body.ScrollRectangle.Size.Height < this.wbNoteContainer.Size.Height))
{
this.wbNoteContainer.Document.Body.Style = "overflow:hidden";
}
Problem get solved..!
In my Windows Phone app's main page, users can click a button to do some stuff and that will trigger the live tile to update.
The problem I am having is, if the user clicks the button and then hit the phone's Back button really quickly, the live tile sometimes will not render properly. This issue rarely happens, but it does happen and when it happens it just looks bad...
The way I implement the live tile is, create a user control that looks exactly the same as the live tile and then save it to isolated storage. Then retrieve it and store it in a FliptileData object. Finally I call the Update method on the ShellTile. Please see the following piece of code to demonstrate the process.
// the function that saves the user control to isolated storage
public Uri SaveJpegToIsolatedStorage(FrameworkElement tile, string suffix, int tileWidth = 336, int tileHeight = 336)
{
var bmp = new WriteableBitmap(tileWidth, tileHeight);
// Force the content to layout itself properly
tile.Measure(new Size(tileWidth, tileHeight));
tile.Arrange(new Rect(0, 0, tileWidth, tileHeight));
bmp.Render(tile, null);
bmp.Invalidate();
// Obtain the virtual store for the application
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
using (IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(IsolatedStorageFileName + suffix, FileMode.Create, myStore))
{
try
{
bmp.SaveJpeg(fileStream, tileWidth, tileHeight, 0, 100);
}
catch (Exception)
{
return null;
}
}
return new Uri("isostore:/" + IsolatedStorageFileName + suffix, UriKind.Absolute);
}
// save the user control to isolated storage and prepare the FlipTileData object
wideFrontTileImage = SaveJpegToIsolatedStorage((UserControl)this.WideFrontTile, "_wide_front", 691);
var flipTileData = new FlipTileData();
flipTileData.WideBackgroundImage = wideFrontTileImage;
return flipTileData;
// update the live tile
var shellTile = ShellTile.ActiveTiles.FirstOrDefault();
shellTile.Update(customTile.GetFlipTileData(data.UndoneMemosCount == "0" && data.TotalMemosCount == "0"));
I think the reason that's causing all this is, when the user clicks the Back button too quickly, the OS terminates all the processes running within the app and the rendering wasn't done at that time. I'm thinking if there's a way to know when the rendering is finished, so I can cancel the Back button and wait until it's finished then manually exit the app. But I simply dunno how...
Any help on this one will be greatly appreciated!
I have ran into similar issue in my WP8 app. The problem was that I was updating my Tile in ApplicationDeactivated event handler. The thing is you should not update your tiles there, but rather in your MainPage.OnNavigatedFrom override. Once I changed this, it works just fine.
I have a requirement to download a file from the server, but open inline if possible. I'm currently doing;
Response.AddHeader("Content-Disposition", string.Format("inline; filename={0}", documentFileName));
result = new FileStreamResult(new FileStream(documentFilePath, FileMode.Open), "application/msword");
I've put application/msword in there right now, because that's what I'm having a problem with. When I click Open on the word document, it's as if the document makes multiple calls back to the action, but there is no session and no database so it crashes. When the user is running this, they see a long hang, the "Downloading" dialog finally appears in word and they have to cancel it. The document is there and is valid but this is not desirable.
Pdfs, pngs etc. download fine. Can anybody explain this behavior, and give me some hints as to how I fix it?
Update:
The action basically looks like;
[HttpPost]
public FileResult View(int id, int source)
{
var document = GetDocumentFromDatabase(id, source);
documentFilePath = Path.Combine( documentsDirectory, document.Name);
documentName = document.Name;
Response.AddHeader("Content-Disposition", string.Format("inline; filename={0}", documentFileName));
result = new FileStreamResult(new FileStream(documentFilePath, FileMode.Open), "application/msword");
return result;
}
I've trimmed it down, as I can't share the specifics, but the full idea is there.
Answer:
I have a lookup of available content-types, in there I have defined whether the file is inline or attachment, and when I detect a word document, I set it to attachment. No more error. PDF opens in the browser still because I set it to inline.
I use:
public ActionResult GetAttachment(int id)
{
var attachment = _repository.GetAttachByID(id);
if (attachment != null)
{
Response.AppendHeader("Content-Disposition",string.Format("inline; filename={0}",attachment.FileName));
return File(attachment.File, attachment.MimeType, attachment.FileName);
}
else
{
return null;
}
}
Regards
How can i get the IADs interface of an Active Directory user - by username?
Note: Native code
i am trying to write the function that can get the IADs interface of a user in Active Directory.
i have the following "pseudocode" so far:
public IADs GetUserObject(string samAccountName)
{
IADs ads;
//Get the current domain's distinguished name ("dc=stackoverflow,dc=com")
AdsGetObject("LDAP://rootDSE", IADs, ref ads);
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
String path;
//Attempt #1 to bind to a user by username
path = "LDAP://sSAMAccountName="+samAccountName+",dc=stackoverflow,dc=com"
AdsGetObject(path, IADs, ref ads); //invalid syntax
return ads;
}
The trick, that i cannot figure out, is how to bind to the user by their account name. The following variantions don't work:
LDAP://sSAMAccountName=ian,dc=stackoverflow,dc=com
LDAP://dc=stackoverflow,dc=com;(&(objectCategory=user)(sAMAccountName=ian))
<LDAP://dc=stackoverflow,dc=com>;(&(objectCategory=user)(sAMAccountName=ian))
Edit:
A version that does work, but doesn't answer my question, is:
LDAP://cn=Ian Boyd,ou=Avatar Users,dc=stackoverflow,dc=com
It doesn't answer my question for two reasons:
i don't know the user's CN (Common-Name) (e.g. Ian Boyd), only their sAMAccountName (e.g. ian)
doesn't work for users not in the Avatar Users organizational unit; and i don't know a user's OU
Which comes from the notes i had before:
Note:
i don't know the name of the domain (but that's okay, i can get it at runtime)
i don't know the name of any active directory servers
i don't know the folder that the user is in
tl;dr: How would you write the utility function:
public IADs GetUserObject(string samAccountName)
{
//TODO: ask stackoverflow
}
Update 2:
Note:
i already know how to query for information about a user using .NET's DirectorySearcher
i already know how to query for information about a user using the Active Directory Services OLEDB provider with ADO (using the SQL syntax, but not the native syntax)
i'm now looking for code to query for information about a user using Active Directory Services COM objects (hence the question about getting an IADs for a user)
Update 3:
It certainly might require me to apply "filters", except i don't know where. The only ActiveDs interface that mentions Filter is IADSContainer, but i don't know where to get one.
i tried randomly to get the IADsContainer interface from the root IADs interface, but "rootDSE" doesn't support IADsContainer:
IADs ads = AdsGetObject("LDAP://rootDSE");
IADsContainer container = (IADsContainer)ads; //interface not supported exception
i could
ask a question on how to get the IADsContainer of the AD root
so i can ask how to recursively search active diretory
so i can ask how to filter using IADsContainer
so i can figure out how to get the IADs object of a user
so i an figure out how to query AD for user properties
But keeping track of all these questions is difficult.
If you know the value of sAMAccountName and need to get IADs of the user you need first find the user in Active Directory by the sAMAccountName and get distinguishedName attribute of the user. You know already how to get IADs by distinguishedName.
So you should just follow the code from MSDN for example. First you get IDirectorySearch interface of the AD container of defaultNamingContext of "LDAP://rootDSE".
IADs domain;
ADsGetObject("LDAP://rootDSE", IADs, domain);
Then you use IDirectorySearch::ExecuteSearch to apply search using the filter string:
(&(objectClass=user)(objectCategory=person)(sAMAccountName=theName))
Note: The search filter syntax is described here.
IDirectorySearch directorySearch = domain as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
directorySearch.ExecuteSearch(
"(&(objectClass=user)(objectCategory=person)(sAMAccountName=ian))",
attributeNames, numberOfAttributes,
out searchHandle);
you use the known value of sAMAccountName instead of theName.
for pAttributeNames you can use LPOLESTR array which consist from L"distinguishedName" only (see pszNonVerboseList from the code example and look the code of FindUsers in case of bIsVerbose as FALSE).
You should get distinguishedName attribute of first (and the only if any exist) found item. Having distinguishedName attribute you can use AdsGetObject to get the IADs of the user.
Alternatively you can get objectGUID attribute of the user instead of distinguishedName attribute and use binding by GUID syntax, but the usage of distinguishedName I personally find more clear and understandable.
public IADs GetUserObject(string samAccountName)
{
IADs ads;
//Get the current domain's distinguished name (e.g. "dc=stackoverflow,dc=com")
AdsGetObject("LDAP://rootDSE", IADs, ref ads);
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
//Get the the object of the current domain (e.g. LDAP://dc=stackoverflow,dc=com)
AdsGetObject("LDAP://"+dn, IADs, ref ads);
//Now we're going to search for the "distinguishedName" of this user
//setup the search filter for the user we want
String filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName="+samAccountName+"))";
//specify that we only need to return one attribute, distinguishedNamem,
//otherwise it returns all attributes and is a waste of resources
String[] searchAttributes = { "distinguishedName" };
//run the search
IDirectorySearch ds = ads as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
ds.ExecuteSearch(filter, searchAttributes, 1, out searchHandle);
ds.GetFirstRow(searchHandle);
//Now get the details of the "distinguishedName" column
ADS_SEARCH_COLUMN column;
ds.GetColumn(searchHandle, "distinguishedName", ref column);
//Get the user's distinguishedName
String dn = column.pADsValues.DNString;
//Now that we have the user's distinguishedName, we can do what we really wanted:
AdsGetObject("LDAP://"+dn, IADs, ads);
return ads;
}
This means that conceptually it can be broken down into two steps:
getting a user's distinguishedName from their samAccountName
fetching the IADs for a distinguishedName
And splitting the code:
public IADs GetUserObject(string samAccountName)
{
String userDistinguishedName = GetUserDistinguishedName(samAccountName);
return GetObject("LDAP://"+userDistingishedName);
}
public String GetUserDistinguishedName(string samAccountName)
{
//Get the current domain's distinguished name (e.g. "dc=stackoverflow,dc=com")
IADs ads = GetObject("LDAP://rootDSE");
String dn = ads.Get("defaultNamingContext"); //"dc=stackoverflow,dc=com"
//Get the the object of the current domain (e.g. LDAP://dc=stackoverflow,dc=com)
ads := GetObject("LDAP://"+dn);
//Now we're going to search for the "distinguishedName" of this user
//setup the search filter for the user we want
String filter = '(&(objectClass=user)(objectCategory=person)(sAMAccountName='+samAccountName+'))';
//specify that we only need to return one attribute, distinguishedNamem,
//otherwise it returns all attributes and is a waste of resources
String[] searchAttributes = { "distinguishedName" };
//run the search
IDirectorySearch ds = ads as IDirectorySearch;
ADS_SEARCH_HANDLE searchHandle;
ds.ExecuteSearch(filter, searchAttributes, 1, out searchHandle);
ds.GetFirstRow(searchHandle);
//Now get the details of the "distinguishedName" column
ADS_SEARCH_COLUMN column;
ds.GetColumn(searchHandle, "distinguishedName", ref column);
//Get the user's distinguishedName
return column.pADsValues.DNString;
}
Here is a sample in C++
IADs *pObject;
HRESULT hr;
// Initialize COM.
CoInitialize(NULL);
hr = ADsGetObject(L"LDAP://CN=JPB,OU=MonOU,DC=societe,DC=fr",
IID_IADs,
(void**) &pObject);
if(SUCCEEDED(hr))
{
// Use the object.
// Release the object.
pObject->Release()
}
// Uninitialize COM.
CoUninitialize();
You can find more information in Binding to Active Directory Domain Services.