I need to access a memory mapped file from one of my routes in my Web API. Using the normal IIS worker settings I have no luck and my service always returns "File not found". I tried to add the prefix "Global/" but still no luck.
After reading many hours on the web I learned that I need to change the Identity of the IIS worker. So, just for testing purposes I changed the worker identity to the Administrator account. I uploaded a picture here:
http://imgur.com/MrA3byz
But still no luck. Does anyone here know how to configure IIS correctly?
Here is how I access the Memory Mapped File using c#:
string Message = "";
try
{
string MMF_In_Name = "Global\\MMF_Name";
MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name);
Messages.Add("Connected to MMF");
}
catch (Exception ex)
{
Messages.Add(ex.Message);
}
I have double checked the name of the memory mapped file and it's correct. A command line tool run as Administrator works as expected.
I'm using IIS 8.5 on Windows Server 2012.
This works on Windows Server 2012 and IIS 8.5.
It's important to understand that the IIS worker runs in a different Terminal Server Session than normal applications. Much like a Windows Service.
So when the application exposing a Memory Mapped File it needs create it via the "Global\" prefix added to the name. But it also needs add a security descriptor or identity. In c# it would look like this:
string MMF_Name = #"Global\MyMemoryMappedFileName";
var security = new MemoryMappedFileSecurity();
security.AddAccessRule(new System.Security.AccessControl.AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null)
, MemoryMappedFileRights.FullControl
, AccessControlType.Allow)
);
var mmf = MemoryMappedFile.CreateOrOpen(MMF_Name
, 1024 * 1024
, MemoryMappedFileAccess.ReadWrite
, MemoryMappedFileOptions.None
, security
, System.IO.HandleInheritability.Inheritable);
In C++ it would look like this:
TCHAR szName[] = TEXT("Global\MyMemoryMappedFileName");
HANDLE hMapFile;
LPCTSTR pBuf;
SECURITY_DESCRIPTOR sd;
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
printf("InitializeSecurityDescriptor failed %d\n", GetLastError());
if (!SetSecurityDescriptorDacl(&sd, true, 0, false))
printf("SetSecurityDescriptorDacl failed %d\n", GetLastError());
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = false;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
&sa, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
An application creating such objects needs to start with Admin rights.
Now when a client like the IIS worker tries to access the file it needs to make sure to use the correct name, aka use the "Global\" prefix. In C# it would look like:
string MMF_Name = #"Global\MyMemoryMappedFileName";
var MMF = MemoryMappedFile.OpenExisting(MMF_Name
, MemoryMappedFileRights.ReadWrite
, HandleInheritability.Inheritable);
In C++:
TCHAR szName[] = TEXT("Global\\MyMemoryMappedFileName");
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
TRUE, // !!!!! do inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
When all this is done. The IIS worker should be able to access the application via the memory mapped file. No need to change the identity of the worker. In fact, I run it in default settings.
Related
I have developed an module to save image in windows shared location
my code works fine development machine in VS 2015 and IIS express.
But when i deploy the code in my IIS sever(IIS 8) and set my appppol.
When it checks the directory exists or no it fails and does not save the image.
in share path. I have tried accessing the shared path from server I am able to open it without issues
I have applied logs to check but it fails that directory does not exit
Sharepath ex:\atse-bs-13450.abc.xyz.com\Sharefolder\PhotoImages
My app pool is set to ApplicationPoolIdentity
public void WriteImage(string Location, string base64Image)
{
try
{
// Check if directory exist
if (Directory.Exists(Location))
{
//location value is set in appSettings;
//"\\atse-bs-13450.abc.xyz.com\Sharefolder\PhotoImages\"
string strImagePath = Location;
// Check file exist in location
if (!File.Exists(Location))
{
if (!string.IsNullOrEmpty(base64Image))
{
using (FileStream stream = new FileStream(strImagePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(Base64String2Blob(base64Image));
}
}
}
else
{
strBlobLogMessage = "image file could not be stored on shared location , Share path location : ";
PathNotFound(strBlobLogMessage);
}
}
else
{
strBlobLogMessage = "image file could not be stored on shared location as path does not exists , Share path location : ";
PathNotFound(strBlobLogMessage);
}
}
catch (Exception ex)
{
throw ex;
}
}
Two options
Create a user account and then assign that user account read and write access on shared location. Then you can set the Application Pool Identity to Custom account and then set it to newly created user account.
Since your app pool is using Application Pool Identity, there will be user account with name IIS AppPool\{Applicaiton Pool name} e.g. for DefaultAppPool the user account is IIS AppPool\DefaultAppPool so you can allow read/write access to shared directory to Applicaiton Pool user
This is my first time ever with Sharepoint. Here is the scenario
I have a stand alone web application
I also have a stand alone sharepoint server.
Both are on different servers.
I need to upload a file from web application to sharepoint
I found 2 methods online,
Using the webservice provided by Sharepoint (CopyIntoItems)
Using jQuery library of Sharepoint webservice
After searching the web, I think the jQuery part will not work (you can correct me).
I am looking for a method that takes username/password and uploads a pdf file to Sharepoint server. The following is my C# code that tries to upload but ends up in error
public bool UploadFile(string file, string destination)
{
bool success = false;
CopySoapClient client = new CopySoapClient();
if (client.ClientCredentials != null)
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
try
{
client.Open();
string filename = Path.GetFileName(file);
string destinationUrl = destination + filename;
string[] destinationUrls = { destinationUrl };
FieldInformation i1 = new FieldInformation { DisplayName = "Title", InternalName = "Title", Type = FieldType.Text, Value = filename };
FieldInformation[] info = { i1 };
CopyResult[] result;
byte[] data = File.ReadAllBytes(file);
//uint ret = client.CopyIntoItems(filename, destinationUrls, info, data, out result);
uint ret = client.CopyIntoItems(file, destinationUrls, info, data, out result);
if (result != null && result.Length > 0 && result[0].ErrorCode == 0)
success = true;
}
finally
{
if (client.State == System.ServiceModel.CommunicationState.Faulted)
client.Abort();
if (client.State != System.ServiceModel.CommunicationState.Closed)
client.Close();
}
return success;
}
I am calling the above function like this
UploadFile(#"C:\temp\uploadFile.txt", "http://spf-03:300/demo/Dokumente").ToString();
Error that i get:
Error Code: Destination Invalid
Error Message: The service method 'Copy' must be called on the same domain that contains the target URL.
There is the 3rd option with SharePoint 2010 and that is to use the Client Side object model. The client side object model a a sub set of the larger Sharepoint API, but it does cover uploading documents. Below is blog post with an example of uploading.
Upload document through client object model
As with most things in SharePoint you will need to authenticate against it the site, so find out if your site collection is forms based or claims based and then you should be able to find sample code for your situation.
Solution to the problem:
The problem was that the "security token webservice" was not working and it was giving some error when we manually ran the webservice.
The server was unable to process the request due to an internal error.
For more information about the error, either turn on
IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute
or from the configuration behavior) on the server in order to send the
exception information back to the client, or turn on tracing as per
the Microsoft .NET Framework 3.0 SDK documentation and inspect the
server trace logs.
The above exception is a generic one. To view the exact exception we enabled remote error viewing from the web.config file of the webservice(link) and saw the exact exception.
We found the solution for the exception and the service started. After that everything was working fine.
I need to know a way to connect to a FTP site and i am unable to find an example to do the program using C#.
I need to write the code where i could connect, and download files from the FTP server without using third party component.
How can i do this ? Help.
There is FtpWebRequest class in .Net 4
http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx
There are examples at the end. Here is a sample taken from msdn:
public static bool DisplayFileFromServer(Uri serverUri)
{
// The serverUri parameter should start with the ftp:// scheme.
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return false;
}
// Get the object used to communicate with the server.
WebClient request = new WebClient();
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe#contoso.com");
try
{
byte [] newFileData = request.DownloadData (serverUri.ToString());
string fileString = System.Text.Encoding.UTF8.GetString(newFileData);
Console.WriteLine(fileString);
}
catch (WebException e)
{
Console.WriteLine(e.ToString());
}
return true;
}
This isn't specifically a question as such.
You need to use the socket classes within the .NET framework:
MSDN - System.Net.Sockets
A good example I've previously used is:
www.dreamincode.net - Create an ftp class library
When using Directory services in IIS7, I am unable to get the invoke(method) to work with the app pool. It consistently returns the unknown name exception.
Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
I am able to use the InvokeGet command to get property data from the app pool, but invoke consistently fails. It's as if the method names were changed between IIS6 and IIS7.
The code is run by a web page running on an Windows 2003 box with IIS6, It is querying a Windows 2008 box with IIS7.5
Here is my code:
string machineName = this.MYMACH.Text;
string query;
string Usrnm = GetUSRNAME(); //decrypts admin user name
string Pswd = GetPSWORD(); //decrypts admin user password
query = String.Format("IIS://{0}/w3svc/AppPools/{1}", machineName, AppPoolName);
DirectoryEntry w3svc = new DirectoryEntry(query, Usrnm, Pswd);
try
{
if (4 == (int)w3svc.InvokeGet("AppPoolState")) // <--- works
{
w3svc.Invoke("Start", null);
errormsgs.Text = string.Format("Application pool {0} retarted", btn.Text);
}
else
{
w3svc.Invoke("Recycle", null); <--- Excepts
errormsgs.Text = string.Format("Application pool {0} recycled", btn.Text);
}
}
catch (Exception eee)
{
errormsgs.Text = string.Format("Application pool {0} recycle error {1}... Query text = {2}", btn.Text, eee.Message, query);
}
I've tried the invoke several ways:
w3svc.Invoke("Recycle", null);
w3svc.Invoke("Recycle", object[]{});
w3svc.Invoke("Recycle");
None of them work
any ideas?
This is because your code doesn't have the right to use local DCOM to do the invoke.
Try :
<system.web>
<identity impersonate="true" userName="" password="" />
</system.web>
Make sure you use a local domain account have the right to use DCOM on this machine.
Also, you can change the local DCOM setting to give your local app pool user rights.
Can anyone help create an Application Pool in IIS using C#?
Once this has been done, how do I assign the Application Pool to a virtual directory, again using C#?
If you're using IIS7:
To create an application pool using and set the .NET Framework version (to v2.0 in this case), do this:
using Microsoft.Web.Administration;
...
using(ServerManager serverManager = new ServerManager())
{
ApplicationPool newPool = serverManager.ApplicationPools.Add("MyNewPool");
newPool.ManagedRuntimeVersion = "v2.0";
serverManager.CommitChanges();
}
You should add a reference to Microsoft.Web.Administration.dll which can be found in:
%SYSTEMROOT%\System32\InetSrv
To assign a virtual directory to an application pool (though I think you mean an application):
using (ServerManager serverManager = new ServerManager())
{
// Find Default Website
Site site = serverManager.Sites.First(s => s.Id == 1);
Application newApp = site.Applications.Add("/MyNewApp",
#"C:\inetpub\wwwroot\mynewapp");
newApp.ApplicationPoolName = "MyNewPool";
serverManager.CommitChanges();
}
If you're using IIS6:
using (DirectoryEntry appPools =
new DirectoryEntry("IIS://localhost/W3SVC/AppPools"))
{
using (DirectoryEntry newPool = appPools.Children.Add("MyNewPool",
"IIsApplicationPool"))
{
// Just use NetworkService as pool account
newPool.Properties["AppPoolIdentityType"].Value = 2;
newPool.CommitChanges();
}
}
The following code creates an application called MyNewApp in the Default Web Site and assigns it to the application pool MyNewPool we created using the code example above:
using (DirectoryEntry siteRoot =
new DirectoryEntry(#"IIS://Localhost/W3SVC/1/root"))
{
using (DirectoryEntry newApp =
siteRoot.Children.Add("MyNewApp", "IIsWebVirtualDir"))
{
newApp.Properties["Path"].Value = #"C:\inetpub\wwwroot\mynewapp";
newApp.Properties["AccessScript"][0] = true;
newApp.Properties["AccessFlags"].Value = 513; // AccessScript | AccessRead
newApp.Properties["AuthFlags"].Value = 7;// AuthAnonymous|AuthBasic|AuthNTLM
newApp.Properties["AppIsolated"].Value = "2";
newApp.Properties["AppRoot"].Value =
newApp.Path.Replace("IIS://Localhost", "/LM");
newApp.Properties["AppPoolId"].Value = "MyNewPool";
newApp.Properties["AppFriendlyName"].Value = "MyNewApp";
newApp.CommitChanges();
}
}
I all of the above cases your code needs to be running as an administrator.
For more information see:
IIS7:
IIS 7 Configuration Reference
How to Use Microsoft.Web.Administration
IIS6:
Using System.DirectoryServices to Configure IIS
IIS Programmatic Administration Reference
IIS Metabase Properties
I believe this depends on which version of IIS you are using but check out:
http://msdn.microsoft.com/en-us/library/ms525598.aspx (example is for IIS7)
Source was from another question: Programmatically create a web site in IIS using C# and set port number